diff --git a/gShell/gShell/Cmdlets/Directory/Directory.cs b/gShell/gShell/Cmdlets/Directory/Directory.cs index 266e4f5..a328cd2 100644 --- a/gShell/gShell/Cmdlets/Directory/Directory.cs +++ b/gShell/gShell/Cmdlets/Directory/Directory.cs @@ -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 @@ -7049,7 +7051,7 @@ 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 @@ -7057,13 +7059,6 @@ public class NewGAUserCommand : DirectoryBase /// User's name /// [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, @@ -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; } /// @@ -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; } /// @@ -7105,6 +7108,14 @@ public class NewGAUserCommand : DirectoryBase HelpMessage = "User's password")] public string Password { get; set; } + /// + /// A secure string password. + /// + [Parameter(Position = 6, + HelpMessage = "A secure string password.", + ParameterSetName = "SecureString")] + public SecureString SecureStringPassword { get; set; } + /// /// The desired length of the generated password /// @@ -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; } /// @@ -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; } /// @@ -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; } /// @@ -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; } /// @@ -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; } /// @@ -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; @@ -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); + } + } } /// @@ -7432,7 +7481,7 @@ 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 @@ -7440,19 +7489,6 @@ public class SetGAUserCommand : DirectoryBase /// User's name /// [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, @@ -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; } /// @@ -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; } /// @@ -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; } /// @@ -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; } /// @@ -7512,6 +7560,14 @@ public class SetGAUserCommand : DirectoryBase ParameterSetName = "PasswordProvided")] public string NewPassword { get; set; } + /// + /// A secure string password. + /// + [Parameter(Position = 6, + HelpMessage = "A secure string password.", + ParameterSetName = "SecureString")] + public SecureString SecureStringPassword { get; set; } + /// /// The desired length of the generated password /// @@ -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; } /// @@ -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; } /// @@ -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)), @@ -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) { @@ -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) @@ -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); + } + } } }