Skip to content

Commit

Permalink
Added support for SecureString passwords - issue #13
Browse files Browse the repository at this point in the history
  • Loading branch information
squid808 committed Jul 19, 2016
1 parent e81f268 commit c34e13e
Showing 1 changed file with 117 additions and 23 deletions.
140 changes: 117 additions & 23 deletions gShell/gShell/Cmdlets/Directory/Directory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Runtime.InteropServices;
using System.Security;
using Data = Google.Apis.admin.Directory.directory_v1.Data;

namespace gShell.Cmdlets.Directory
Expand Down Expand Up @@ -7049,21 +7051,14 @@ protected override void ProcessRecord()
DefaultParameterSetName = "PasswordGenerated",
SupportsShouldProcess = true,
HelpUri = @"https://github.com/squid808/gShell/wiki/New-GAUser")]
public class NewGAUserCommand : DirectoryBase
public sealed class NewGAUserCommand : DirectoryBase
{
#region Properties

/// <summary>
/// <para type="description">User's name</para>
/// </summary>
[Parameter(Position = 0,
ParameterSetName = "PasswordProvided",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
HelpMessage = "User's name")]
[Parameter(Position = 0,
ParameterSetName = "PasswordGenerated",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Expand All @@ -7082,6 +7077,10 @@ public class NewGAUserCommand : DirectoryBase
ParameterSetName = "PasswordGenerated",
Mandatory = true,
HelpMessage = "First Name")]
[Parameter(Position = 2,
ParameterSetName = "SecureString",
Mandatory = true,
HelpMessage = "First Name")]
public string GivenName { get; set; }

/// <summary>
Expand All @@ -7095,6 +7094,10 @@ public class NewGAUserCommand : DirectoryBase
ParameterSetName = "PasswordGenerated",
Mandatory = true,
HelpMessage = "Full Name")]
[Parameter(Position = 3,
ParameterSetName = "SecureString",
Mandatory = true,
HelpMessage = "Full Name")]
public string FamilyName { get; set; }

/// <summary>
Expand All @@ -7105,6 +7108,14 @@ public class NewGAUserCommand : DirectoryBase
HelpMessage = "User's password")]
public string Password { get; set; }

/// <summary>
/// <para type="description">A secure string password.</para>
/// </summary>
[Parameter(Position = 6,
HelpMessage = "A secure string password.",
ParameterSetName = "SecureString")]
public SecureString SecureStringPassword { get; set; }

/// <summary>
/// <para type="description">The desired length of the generated password</para>
/// </summary>
Expand All @@ -7130,6 +7141,9 @@ public class NewGAUserCommand : DirectoryBase
[Parameter(Position = 7,
ParameterSetName = "PasswordGenerated",
HelpMessage = "Boolean indicating if user is included in Global Address List")]
[Parameter(Position = 7,
ParameterSetName = "SecureString",
HelpMessage = "Boolean indicating if user is included in Global Address List")]
public bool? IncludeInDirectory { get; set; }

/// <summary>
Expand All @@ -7141,6 +7155,9 @@ public class NewGAUserCommand : DirectoryBase
[Parameter(Position = 8,
ParameterSetName = "PasswordGenerated",
HelpMessage = "Indicates if user is suspended")]
[Parameter(Position = 8,
ParameterSetName = "SecureString",
HelpMessage = "Indicates if user is suspended")]
public bool? Suspended { get; set; }

/// <summary>
Expand All @@ -7152,6 +7169,9 @@ public class NewGAUserCommand : DirectoryBase
[Parameter(Position = 9,
ParameterSetName = "PasswordGenerated",
HelpMessage = "Boolean indicating if ip is whitelisted")]
[Parameter(Position = 9,
ParameterSetName = "SecureString",
HelpMessage = "Boolean indicating if ip is whitelisted")]
public bool? IpWhiteListed { get; set; }

/// <summary>
Expand All @@ -7165,6 +7185,10 @@ public class NewGAUserCommand : DirectoryBase
ParameterSetName = "PasswordGenerated",
ValueFromPipelineByPropertyName = true,
HelpMessage = "Boolean indicating if the user should change password in next login")]
[Parameter(Position = 10,
ParameterSetName = "SecureString",
ValueFromPipelineByPropertyName = true,
HelpMessage = "Boolean indicating if the user should change password in next login")]
public bool? ChangePasswordAtNextLogin { get; set; }

/// <summary>
Expand All @@ -7176,6 +7200,9 @@ public class NewGAUserCommand : DirectoryBase
[Parameter(Position = 11,
ParameterSetName = "PasswordGenerated",
HelpMessage = "OrgUnit of User")]
[Parameter(Position = 11,
ParameterSetName = "SecureString",
HelpMessage = "OrgUnit of User")]
public string OrgUnitPath { get; set; }

/// <summary>
Expand Down Expand Up @@ -7229,6 +7256,11 @@ private void CreateUser()
userAcct.HashFunction = "MD5";
userAcct.Password = GeneratePassword(PasswordLength, ShowNewPassword);
break;

case "SecureString":
userAcct.HashFunction = "MD5";
userAcct.Password = GetMd5Hash(ConvertToUnsecureString(SecureStringPassword));
break;
}

if (IncludeInDirectory.HasValue) userAcct.IncludeInGlobalAddressList = IncludeInDirectory;
Expand All @@ -7243,6 +7275,23 @@ private void CreateUser()

users.Insert(userAcct);
}

private string ConvertToUnsecureString(SecureString securePassword)
{
if (securePassword == null)
throw new ArgumentNullException("securePassword");

IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}

/// <summary>
Expand Down Expand Up @@ -7432,27 +7481,14 @@ private void RestoreUser()
DefaultParameterSetName = "NoPasswordProvided",
SupportsShouldProcess = true,
HelpUri = @"https://github.com/squid808/gShell/wiki/Set-GAUser")]
public class SetGAUserCommand : DirectoryBase
public sealed class SetGAUserCommand : DirectoryBase
{
#region Properties

/// <summary>
/// <para type="description">User's name</para>
/// </summary>
[Parameter(Position = 0,
ParameterSetName = "PasswordProvided",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
HelpMessage = "The username of the user to update.")]
[Parameter(Position = 0,
ParameterSetName = "PasswordGenerated",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
HelpMessage = "The username of the user to update.")]
[Parameter(Position = 0,
ParameterSetName = "Body",
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
Expand All @@ -7469,6 +7505,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 2,
ParameterSetName = "PasswordGenerated",
HelpMessage = "The user's first name. Required when creating a user account.")]
[Parameter(Position = 2,
ParameterSetName = "SecureString",
HelpMessage = "The user's first name. Required when creating a user account.")]
public string NewGivenName { get; set; }

/// <summary>
Expand All @@ -7480,6 +7519,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 3,
ParameterSetName = "PasswordGenerated",
HelpMessage = "The user's last name. Required when creating a user account.")]
[Parameter(Position = 3,
ParameterSetName = "SecureString",
HelpMessage = "The user's last name. Required when creating a user account.")]
public string NewFamilyName { get; set; }

/// <summary>
Expand All @@ -7491,6 +7533,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 4,
ParameterSetName = "PasswordGenerated",
HelpMessage = "The user's username, post-update.")]
[Parameter(Position = 4,
ParameterSetName = "SecureString",
HelpMessage = "The user's username, post-update.")]
public string NewUserName { get; set; }

/// <summary>
Expand All @@ -7502,6 +7547,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 5,
ParameterSetName = "PasswordGenerated",
HelpMessage = "Indicates if the user is suspended.")]
[Parameter(Position = 5,
ParameterSetName = "SecureString",
HelpMessage = "Indicates if the user is suspended.")]
public bool? Suspended { get; set; }

/// <summary>
Expand All @@ -7512,6 +7560,14 @@ public class SetGAUserCommand : DirectoryBase
ParameterSetName = "PasswordProvided")]
public string NewPassword { get; set; }

/// <summary>
/// <para type="description">A secure string password.</para>
/// </summary>
[Parameter(Position = 6,
HelpMessage = "A secure string password.",
ParameterSetName = "SecureString")]
public SecureString SecureStringPassword { get; set; }

/// <summary>
/// <para type="description">The desired length of the generated password</para>
/// </summary
Expand All @@ -7537,6 +7593,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 9,
ParameterSetName = "PasswordGenerated",
HelpMessage = "Indicates if the user is forced to change their password at next login.")]
[Parameter(Position = 9,
ParameterSetName = "SecureString",
HelpMessage = "Indicates if the user is forced to change their password at next login.")]
public bool? ChangePasswordAtNextLogin { get; set; }

/// <summary>
Expand All @@ -7548,6 +7607,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 10,
ParameterSetName = "PasswordGenerated",
HelpMessage = "The full path of the parent organization associated with the user. If the parent organization is the top-level, it is represented as a forward slash (/).")]
[Parameter(Position = 10,
ParameterSetName = "SecureString",
HelpMessage = "The full path of the parent organization associated with the user. If the parent organization is the top-level, it is represented as a forward slash (/).")]
public string OrgUnitPath { get; set; }

/// <summary>
Expand All @@ -7559,6 +7621,9 @@ public class SetGAUserCommand : DirectoryBase
[Parameter(Position = 11,
ParameterSetName = "PasswordGenerated",
HelpMessage = "A supplied property collection to update the user with. Create with New/Get-GAUserPropertyCollection and update with New/Remove-GauserProperty")]
[Parameter(Position = 11,
ParameterSetName = "SecureString",
HelpMessage = "A supplied property collection to update the user with. Create with New/Get-GAUserPropertyCollection and update with New/Remove-GauserProperty")]
public GAUserPropertyCollection PropertyCollection { get; set; }

/// <summary>
Expand Down Expand Up @@ -7603,7 +7668,8 @@ private void UpdateUser()
ShowNewPassword == false &&
!Suspended.HasValue &&
!ChangePasswordAtNextLogin.HasValue &&
null == PropertyCollection)
null == PropertyCollection &&
null == SecureStringPassword)
{
WriteError(new ErrorRecord(new Exception(
string.Format("No data was entered to update {0}.", UserKey)),
Expand All @@ -7614,16 +7680,22 @@ private void UpdateUser()
userAcct.Suspended = Suspended.Value;

if (!String.IsNullOrWhiteSpace(NewGivenName))
{
if (userAcct.Name == null) userAcct.Name = new Data.UserName();
userAcct.Name.GivenName = NewGivenName;
}

if (!String.IsNullOrWhiteSpace(NewFamilyName))
{
if (userAcct.Name == null) userAcct.Name = new Data.UserName();
userAcct.Name.FamilyName = NewFamilyName;
}

if (!String.IsNullOrWhiteSpace(NewUserName))
{
NewUserName = GetFullEmailAddress(NewUserName, Domain);
userAcct.PrimaryEmail = NewUserName;
}

switch (ParameterSetName)
{
Expand All @@ -7636,6 +7708,11 @@ private void UpdateUser()
userAcct.HashFunction = "MD5";
userAcct.Password = GeneratePassword(PasswordLength, ShowNewPassword);
break;

case "SecureString":
userAcct.HashFunction = "MD5";
userAcct.Password = GetMd5Hash(ConvertToUnsecureString(SecureStringPassword));
break;
}

if (ChangePasswordAtNextLogin.HasValue)
Expand Down Expand Up @@ -7671,6 +7748,23 @@ private void UpdateUser()

users.Patch(userAcct, UserKey);
}

private string ConvertToUnsecureString(SecureString securePassword)
{
if (securePassword == null)
throw new ArgumentNullException("securePassword");

IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}
}

Expand Down

0 comments on commit c34e13e

Please sign in to comment.