/* * Changes the password for currently logged in user */ public static void ChangePassword(ApplicationContext context, Node args) { // Retrieving new password, and doing some basic sanity check. string password = args.GetExValue(context, ""); if (string.IsNullOrEmpty(password)) { throw new LambdaException("No password supplied", args, context); } string username = context.Ticket.Username; // Retrieving system salt before we enter write lock. var serverSalt = context.RaiseEvent(".p5.auth.get-server-salt").Get <string> (context); // Locking access to password file as we edit user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Changing user's password // Then salting password with user salt and system, before salting it with system salt var userPasswordFingerprint = context.RaiseEvent("p5.crypto.hash.create-sha256", new Node("", serverSalt + password)).Get <string> (context); authFile ["users"] [username] ["password"].Value = userPasswordFingerprint; }); }
/* * Changes the password for currently logged in user. */ public static void ChangeMyPassword(ApplicationContext context, Node args) { // Retrieving new password. var password = args.GetExValue(context, ""); // Verifying new password is good. if (!IsGoodPassword(context, password)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException( "Password didn't obey by your configuration settings, which are as follows; " + PasswordRuleDescription(context), args, context); } // Figuring out username of current context. var username = context.Ticket.Username; // Salting and hashing password before we enter "auth" file lock to minimize the amount of time file is locked. password = SaltAndHashPassword(context, password); // Locking access to password file as we edit user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Changing user's password by first salting it, and then hashing it. authFile ["users"] [username] ["password"].Value = password; }); }
/* * Changes password of "root" account, but only if existing root account's password * is null. Used during setup of system */ public static void SetRootPassword(ApplicationContext context, Node args) { // Retrieving password given. var password = args.GetExChildValue <string> ("password", context); // Verifying password is accepted. if (!Passwords.IsGoodPassword(context, password)) { // Password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException( "Password didn't obey by your configuration settings, which are as follows; " + Passwords.PasswordRuleDescription(context), args, context); } // Creating root account. var rootAccountNode = new Node("", "root"); rootAccountNode.Add("password", password); rootAccountNode.Add("role", "root"); Users.CreateUser(context, rootAccountNode); // Creating "guest account" section, which is needed for settings among other things. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { authFile ["users"].Add(context.RaiseEvent(".p5.auth.get-default-context-username").Get <string> (context)).LastChild .Add("role", context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)); }); }
/* * Retrieves a specific user from system */ public static void DeleteUser(ApplicationContext context, Node args) { // Locking access to password file as we create new user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Iterating all users requested deleted by caller foreach (var idxUsername in XUtil.Iterate <string> (context, args)) { // Checking if user exist if (authFile ["users"] [idxUsername] == null) { throw new LambdaException( string.Format("User '{0}' does not exist", idxUsername), args, context); } // Deleting currently iterated user authFile["users"][idxUsername].UnTie(); // Deleting user's home directory context.Raise("p5.io.folder.delete", new Node("", "/users/" + idxUsername + "/")); } }); }
/* * Edits an existing user */ public static void EditUser(ApplicationContext context, Node args) { // Retrieving username, and sanity checking invocation. string username = args.GetExValue <string> (context); if (args ["username"] != null) { throw new LambdaSecurityException("Cannot change username for user", args, context); } // Retrieving new password and role, defaulting to null, which will not update existing values. string newPassword = args.GetExChildValue <string> ("password", context); string newRole = args.GetExChildValue <string> ("role", context); // Retrieving system salt before we enter write lock. (important, since otherwise we'd have a deadlock condition here). var serverSalt = newPassword == null ? null : context.RaiseEvent(".p5.auth.get-server-salt").Get <string> (context); // Locking access to password file as we edit user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking to see if user exist. if (authFile ["users"] [username] == null) { throw new LambdaException( "Sorry, that user does not exist", args, context); } // Updating user's password, but only if a new password was supplied by caller. if (!string.IsNullOrEmpty(newPassword)) { // Making sure we salt password with system salt, before we create our SHA256 value, which is what we actually store in our "auth" file. var userPasswordFingerprint = context.RaiseEvent("p5.crypto.hash.create-sha256", new Node("", serverSalt + newPassword)).Get <string> (context); authFile ["users"] [username] ["password"].Value = userPasswordFingerprint; } // Updating user's role, if a new role was supplied by caller. if (newRole != null) { authFile ["users"] [username] ["role"].Value = newRole; } // Checking if caller wants to edit settings. if (args.Name == "p5.auth.users.edit") { // Removing old settings. authFile ["users"] [username].RemoveAll(ix => ix.Name != "password" && ix.Name != "role"); // Adding all other specified objects to user. foreach (var idxNode in args.Children.Where(ix => ix.Name != "password" && ix.Name != "role")) { authFile ["users"] [username].Add(idxNode.Clone()); } } }); }
/* * Sets the GnuPG keypair for server. */ public static void SetFingerprint(ApplicationContext context, Node args, string fingerprint) { AuthFile.ModifyAuthFile(context, delegate(Node node) { if (node [GnuPgpFingerprintNodeName] != null) { throw new LambdaSecurityException("Tried to change GnuPG keypair after initial creation", args, context); } node.Add(GnuPgpFingerprintNodeName, fingerprint); }); }
/* * Sets the server salt for application */ public static void SetServerSalt(ApplicationContext context, Node args, string salt) { AuthFile.ModifyAuthFile(context, delegate(Node node) { if (node.Children.Find(delegate(Node ix) { return(ix.Name == "server-salt"); }) != null) { throw new LambdaSecurityException("Tried to change server salt after initial creation", args, context); } node.FindOrInsert("server-salt").Value = salt; }); }
/* * Edits an existing user */ public static void EditUser(ApplicationContext context, Node args) { string username = args.GetExValue <string>(context); string password = args.GetExChildValue <string>("password", context); string userRole = args.GetExChildValue <string>("role", context); if (args["username"] != null) { throw new LambdaSecurityException("Cannot change username for user", args, context); } // Locking access to password file as we edit user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking to see if user exist if (authFile["users"][username] == null) { throw new LambdaException( "Sorry, that user does not exist", args, context); } // Updating user's password, if a new one was given if (!string.IsNullOrEmpty(password)) { // Changing user's password // Creating user salt, and retrieving system salt var serverSalt = context.Raise(".p5.auth.get-server-salt").Get <string> (context); // Then salting password with user salt and system, before salting it with system salt var userPasswordFingerprint = context.Raise("p5.crypto.hash.create-sha256", new Node("", serverSalt + password)).Get <string> (context); authFile ["users"][username]["password"].Value = userPasswordFingerprint; } // Updating user's role if (userRole != null) { authFile["users"][username]["role"].Value = userRole; } // Removing old settings authFile["users"][username].Children.RemoveAll(ix => ix.Name != "password" && ix.Name != "role"); // Adding all other specified objects to user foreach (var idxNode in args.Children.Where(ix => ix.Name != "password" && ix.Name != "role")) { authFile["users"][username].Add(idxNode.Clone()); } }); }
/* * Sets the server salt for server. */ public static void SetServerSalt(ApplicationContext context, Node args, byte[] salt) { using (var sha512 = SHA512.Create()) { salt = sha512.ComputeHash(salt); } AuthFile.ModifyAuthFile(context, delegate(Node node) { if (node.Children.Any(ix => ix.Name == "server-salt")) { throw new LambdaSecurityException("Tried to change server salt after initial creation", args, context); } node.Add("server-salt", salt); }); }
/* * Returns all access objects for system. */ public static void SetAccess(ApplicationContext context, Node args) { // Locking access to password file as we create new access object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Verifying access rights exists. if (authFile ["access"] == null) { authFile.Add("access"); } // Retrieving access root node. var access = authFile ["access"]; // Clearing all previous access objects. access.Clear(); // Iterating all access objects supplied by caller, adding them to our access node. var newAccessRights = XUtil.Iterate <Node> (context, args).ToList(); foreach (var idxAccess in newAccessRights) { // Sanity checking. var val = idxAccess.GetExValue(context, ""); if (string.IsNullOrEmpty(val)) { // Creating a new random GUID as the ID of our access object. val = Guid.NewGuid().ToString(); idxAccess.Value = val; } else { // Verifying access ID is unique. if (access.Children.Any(ix => ix.Get(context, "") == val)) { throw new LambdaException("Each access right must have a unique name/value combination, and there's already another access right with the same name/value combination in your access list", idxAccess, context); } } // Sanity checking access object. if (idxAccess.Count == 0) { throw new LambdaException("There's no actual content in your access object", idxAccess, context); } // Adding currently iterated access object. access.Add(idxAccess.Clone()); } }); }
/* * Changes the settings for currently logged in user */ public static void ChangeSettings(ApplicationContext context, Node args) { // Getting username for current context. string username = context.Ticket.Username; // Making sure default user cannot change his settings. if (context.Ticket.IsDefault) { throw new LambdaSecurityException("The default user cannot change his settings", args, context); } // Verifying that there's no "funny business" going on here. if (args ["password"] != null || args ["role"] != null) { throw new LambdaSecurityException("You cannot change your password or role with this Active Event", args, context); } // Locking access to password file as we edit user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking if invocation is for a single section, or if it's for everything. var section = args.GetExValue(context, ""); if (string.IsNullOrEmpty(section)) { // Removing old settings authFile ["users"] [username].RemoveAll(ix => ix.Name != "password" && ix.Name != "role"); // Changing all settings for user foreach (var idxNode in args.Children) { authFile ["users"] [username].Add(idxNode.Clone()); } } else if (args.Count == 1) { // Removing old settings authFile ["users"] [username] [section]?.UnTie(); // Changing all settings for user. authFile ["users"] [username].Add(args.FirstChild.Clone()); } else { // Oops, can't set a single section to multiple values. throw new LambdaException("You can't set a single section to multiple values", args, context); } }); }
/* * Changes the settings for currently logged in user */ public static void ChangeSettings(ApplicationContext context, Node args) { string username = context.Ticket.Username; // Locking access to password file as we edit user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Removing old settings authFile["users"][username].Children.RemoveAll(ix => ix.Name != "password" && ix.Name != "role"); // Changing all settings for user foreach (var idxNode in args.Children) { authFile["users"][username].Add(idxNode.Clone()); } }); }
/* * Changes the password for currently logged in user */ public static void ChangePassword(ApplicationContext context, Node args) { // Retrieving new password, and doing some basic sanity check. string password = args.GetExValue(context, ""); if (string.IsNullOrEmpty(password)) { throw new LambdaException("No password supplied", args, context); } // Retrieving password rules from web.config, if any. var pwdRulesNode = new Node(".p5.config.get", "p5.auth.password-rules"); var pwdRule = context.RaiseEvent(".p5.config.get", pwdRulesNode) [0]?.Get(context, ""); if (!string.IsNullOrEmpty(pwdRule)) { // Verifying that specified password obeys by rules from web.config. Regex regex = new Regex(pwdRule); if (!regex.IsMatch(password)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException("Password didn't obey by your configuration settings, which are as follows; " + pwdRule, args, context); } } // Figuring out username of current context. string username = context.Ticket.Username; // Retrieving system salt before we enter write lock. var serverSalt = context.RaiseEvent(".p5.auth.get-server-salt").Get <string> (context); // Locking access to password file as we edit user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Changing user's password // Then salting password with user salt and system, before salting it with system salt var userPasswordFingerprint = context.RaiseEvent("p5.crypto.hash.create-sha256", new Node("", serverSalt + password)).Get <string> (context); authFile ["users"] [username] ["password"].Value = userPasswordFingerprint; }); }
/* * Changes the GnuPG keypair for server. */ public static void ChangeServerPGPKey(ApplicationContext context, string fingerprint, Node args) { // Verifying key exists, both its public key, and its private key. var result = context.RaiseEvent("p5.crypto.pgp-keys.public.list", new Node("p5.crypto.pgp-keys.public.list", fingerprint)); if (result.FirstChild.Name != fingerprint) { throw new LambdaSecurityException("The specified new public key does not exist", args, context); } result = context.RaiseEvent("p5.crypto.pgp-keys.private.list", new Node("p5.crypto.pgp-keys.private.list", fingerprint)); if (result.FirstChild.Name != fingerprint) { throw new LambdaSecurityException("The specified new public key does not exist", args, context); } // Changing key. AuthFile.ModifyAuthFile(context, delegate(Node node) { node [GnuPgpFingerprintNodeName].Value = fingerprint; }); }
/* * Deletes the currently logged in user */ public static void DeleteMyUser(ApplicationContext context, Node args) { // Retrieving username to delete. string username = context.Ticket.Username; // Deleting user's home directory context.Raise("p5.io.folder.delete", new Node("", "/users/" + username + "/")); // Locking access to password file as we delete user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Removing user authFile["users"][username].UnTie(); }); var def = CreateDefaultTicket(context); SetTicket(def); context.UpdateTicket(def); }
/* * Returns all access objects for system. */ public static void DeleteAccess(ApplicationContext context, Node args) { // Locking access to password file as we create new access object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Verifying access rights exists. if (authFile ["access"] == null) { return; } // Iterating all access objects passed in by caller. var access = authFile ["access"]; var delAccess = XUtil.Iterate <Node> (context, args).ToList(); foreach (var idxAccess in delAccess) { // Removing all matches. access.Children.First(ix => ix.Name == idxAccess.Name && ix.Get(context, "") == idxAccess.GetExValue(context, "")).UnTie(); } }); }
/* * Changes password of "root" account, but only if existing root account's password * is null. Used during setup of system */ public static void SetRootPassword(ApplicationContext context, Node args) { // Retrieving password given. string password = args.GetExChildValue <string> ("password", context); // Retrieving password rules from web.config, if any. var pwdRulesNode = new Node(".p5.config.get", "p5.auth.password-rules"); var pwdRule = context.RaiseEvent(".p5.config.get", pwdRulesNode) [0]?.Get(context, ""); if (!string.IsNullOrEmpty(pwdRule)) { // Verifying that specified password obeys by rules from web.config. Regex regex = new Regex(pwdRule); if (!regex.IsMatch(password)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException("Password didn't obey by your configuration settings, which are as follows; " + pwdRule, args, context); } } // Creating root account. var rootAccountNode = new Node("", "root"); rootAccountNode.Add("password", password); rootAccountNode.Add("role", "root"); CreateUser(context, rootAccountNode); // Creating "guest account" section, which is needed for settings among other things. var guestAccountName = context.RaiseEvent(".p5.auth.get-default-context-username").Get <string> (context); AuthFile.ModifyAuthFile( context, delegate(Node authFile) { authFile ["users"].Add(guestAccountName); authFile ["users"] ["guest"].Add("role", context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)); }); }
/* * Creates a new user. */ public static void CreateUser(ApplicationContext context, Node args) { // Retrieving arguments. var username = args.GetExValue <string> (context); var password = args.GetExChildValue <string> ("password", context); var role = args.GetExChildValue <string> ("role", context); // Sanity checking role name towards guest account name. if (role == context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of our guest account role.", args, context); } // Sanity checking username towards guest account name. if (username == context.RaiseEvent(".p5.auth.get-default-context-username").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of our guest account.", args, context); } // Making sure [password] never leaves method in case of an exception. args.FindOrInsert("password").Value = "xxx"; // Retrieving password rules from web.config, if any. if (!Passwords.IsGoodPassword(context, password)) { // New password was not accepted, throwing an exception. throw new LambdaSecurityException( "Password didn't obey by your configuration settings, which are as follows; " + Passwords.PasswordRuleDescription(context), args, context); } // Basic sanity check new user's data. if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(role)) { throw new LambdaException( "User must have username as value, [password] and [role] at the very least", args, context); } // Verifying username is valid, since we'll need to create a folder for user. VerifyUsernameValid(username); // To reduce lock time of "auth" file, we execute Blow Fish hashing before we enter lock. password = Passwords.SaltAndHashPassword(context, password); // Locking access to password file as we create new user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking if user exist from before. if (authFile ["users"] [username] != null) { throw new LambdaException( "Sorry, that [username] is already taken by another user in the system", args, context); } // Adding user. var userNode = authFile ["users"].Add(username).LastChild; // Salting and hashing password, before storing it in "auth" file. userNode.Add("password", password); // Adding user to specified role. userNode.Add("role", role); // Adding all other specified objects to user. userNode.AddRange(args.Children.Where(ix => ix.Name != "password" && ix.Name != "role").Select(ix => ix.Clone())); }); // Creating newly created user's directory structure. CreateUserDirectory(context, username); }
/* * Creates a new user */ public static void CreateUser(ApplicationContext context, Node args) { // Retrieving arguments. string username = args.GetExValue <string> (context); string password = args.GetExChildValue <string> ("password", context); string role = args.GetExChildValue <string> ("role", context); // Sanity checking role name towards guest account name. if (role == context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of our guest account role.", args, context); } // Sanity checking username towards guest account name. if (username == context.RaiseEvent(".p5.auth.get-default-context-username").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of our guest account.", args, context); } // Making sure [password] never leaves method. args.FindOrInsert("password").Value = "xxx"; // Retrieving password rules from web.config, if any. var pwdRulesNode = new Node(".p5.config.get", "p5.auth.password-rules"); var pwdRule = context.RaiseEvent(".p5.config.get", pwdRulesNode) [0]?.Get(context, ""); if (!string.IsNullOrEmpty(pwdRule)) { // Verifying that specified password obeys by rules from web.config. Regex regex = new Regex(pwdRule); if (!regex.IsMatch(password)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException("Password didn't obey by your configuration settings, which are as follows; " + pwdRule, args, context); } } // Basic sanity check. if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(role)) { throw new LambdaException( "User must have username as value, [password] and [role] at the very least", args, context); } // Verifying username is valid, since we'll need to create a folder for user. VerifyUsernameValid(username); // Retrieving system salt before we enter write lock. var serverSalt = context.RaiseEvent(".p5.auth.get-server-salt").Get <string> (context); // Then salting user's password. var userPasswordFingerprint = context.RaiseEvent("p5.crypto.hash.create-sha256", new Node("", serverSalt + password)).Get <string> (context); // Locking access to password file as we create new user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking if user exist from before. if (authFile ["users"] [username] != null) { throw new LambdaException( "Sorry, that [username] is already taken by another user in the system", args, context); } // Adding user. authFile ["users"].Add(username); // Creates a salt and password for user. authFile ["users"].LastChild.Add("password", userPasswordFingerprint); // Adding user to specified role. authFile ["users"].LastChild.Add("role", role); // Adding all other specified objects to user. foreach (var idxNode in args.Children.Where(ix => ix.Name != "username" && ix.Name != "password" && ix.Name != "role")) { // Only adding nodes with some sort of actual value. if (idxNode.Value != null || idxNode.Count > 0) { authFile ["users"].LastChild.Add(idxNode.Clone()); } } }); // Creating newly created user's directory structure. CreateUserDirectory(context.RaiseEvent(".p5.core.application-folder").Get <string> (context), username); }
/* * Creates a new user */ public static void CreateUser(ApplicationContext context, Node args) { string username = args.GetExValue <string>(context); string password = args.GetExChildValue <string>("password", context); string role = args.GetExChildValue <string>("role", context); // Making sure [password] never leaves method, in case of exceptions args.FindOrInsert("password").Value = "xxx"; // Basic syntax checking if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(role)) { throw new LambdaException( "User must have [username], [password] and [role] at the very least", args, context); } // Verifying username is valid, since we'll need to create a folder for user VerifyUsernameValid(username); // Creating user salt, and retrieving system salt var serverSalt = context.Raise(".p5.auth.get-server-salt").Get <string> (context); // Then salting password with user salt, before salting it with system salt var userPasswordFingerprint = context.Raise("p5.crypto.hash.create-sha256", new Node("", serverSalt + password)).Get <string> (context); // Locking access to password file as we create new user object AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking if user exist from before if (authFile["users"][username] != null) { throw new LambdaException( "Sorry, that [username] is already taken by another user in the system", args, context); } // Adding user authFile["users"].Add(username); // Creates a salt and password for user authFile ["users"].LastChild.Add("password", userPasswordFingerprint); // Adding user to specified role authFile ["users"].LastChild.Add("role", role); // Adding all other specified objects to user foreach (var idxNode in args.Children.Where(ix => ix.Name != "username" && ix.Name != "password" && ix.Name != "role")) { // Only adding nodes with some sort of actual value if (idxNode.Value != null || idxNode.Children.Count > 0) { authFile["users"].LastChild.Add(idxNode.Clone()); } } }); // Creating newly created user's directory structure CreateUserDirectory(context.Raise(".p5.core.application-folder").Get <string>(context), username); }
/* * Edits an existing user */ public static void EditUser(ApplicationContext context, Node args) { // Retrieving username, and sanity checking invocation. string username = args.GetExValue <string> (context); if (args ["username"] != null) { throw new LambdaSecurityException("Cannot change username for user", args, context); } // Retrieving new password and role, defaulting to null, which will not update existing values. string newPassword = args.GetExChildValue <string> ("password", context); string newRole = args.GetExChildValue <string> ("role", context); // Sanity checking role name towards guest account name. if (newRole == context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of our guest account role.", args, context); } // Retrieving password rules from web.config, if any. // But only if a new password was given. if (!string.IsNullOrEmpty(newPassword)) { // Verifying password conforms to password rules. var pwdRulesNode = new Node(".p5.config.get", "p5.auth.password-rules"); var pwdRule = context.RaiseEvent(".p5.config.get", pwdRulesNode) [0]?.Get(context, ""); if (!string.IsNullOrEmpty(pwdRule)) { // Verifying that specified password obeys by rules from web.config. Regex regex = new Regex(pwdRule); if (!regex.IsMatch(newPassword)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; throw new LambdaSecurityException("Password didn't obey by your configuration settings, which are as follows; " + pwdRule, args, context); } } } // Retrieving system salt before we enter write lock. (important, since otherwise we'd have a deadlock condition here). var serverSalt = newPassword == null ? null : context.RaiseEvent(".p5.auth.get-server-salt").Get <string> (context); // Locking access to password file as we edit user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking to see if user exist. if (authFile ["users"] [username] == null) { throw new LambdaException( "Sorry, that user does not exist", args, context); } // Updating user's password, but only if a new password was supplied by caller. if (!string.IsNullOrEmpty(newPassword)) { // Making sure we salt password with system salt, before we create our SHA256 value, which is what we actually store in our "auth" file. var userPasswordFingerprint = context.RaiseEvent("p5.crypto.hash.create-sha256", new Node("", serverSalt + newPassword)).Get <string> (context); authFile ["users"] [username] ["password"].Value = userPasswordFingerprint; } // Updating user's role, if a new role was supplied by caller. if (newRole != null) { authFile ["users"] [username] ["role"].Value = newRole; } // Checking if caller wants to edit settings. if (args.Name == "p5.auth.users.edit") { // Removing old settings. authFile ["users"] [username].RemoveAll(ix => ix.Name != "password" && ix.Name != "role"); // Adding all other specified objects to user. foreach (var idxNode in args.Children.Where(ix => ix.Name != "password" && ix.Name != "role")) { authFile ["users"] [username].Add(idxNode.Clone()); } } }); }
/* * Edits an existing user. */ public static void EditUser(ApplicationContext context, Node args) { // Retrieving username, and sanity checking invocation. var username = args.GetExValue <string> (context); if (args ["username"] != null) { throw new LambdaSecurityException("Cannot change username for user", args, context); } // Retrieving new password and role, defaulting to null, which will not update existing values. var password = args.GetExChildValue <string> ("password", context, null); var role = args.GetExChildValue <string> ("role", context, null); // Sanity checking role name towards guest account name. if (role == context.RaiseEvent(".p5.auth.get-default-context-role").Get <string> (context)) { throw new LambdaException("Sorry, but that's the name of your system's guest account role.", args, context); } // Changing user's password, but only if a [password] argument was explicitly supplied by caller. if (!string.IsNullOrEmpty(password)) { // Verifying password conforms to password rules. if (!Passwords.IsGoodPassword(context, password)) { // New password was not accepted, throwing an exception. args.FindOrInsert("password").Value = "xxx"; var description = Passwords.PasswordRuleDescription(context); throw new LambdaSecurityException("Password didn't obey by your configuration settings, which are as follows; " + description, args, context); } } // To reduce lock time of "auth" file we execute Blow Fish hashing before we enter lock. password = password == null ? null : Passwords.SaltAndHashPassword(context, password); // Locking access to password file as we edit user object. AuthFile.ModifyAuthFile( context, delegate(Node authFile) { // Checking to see if user exist. if (authFile ["users"] [username] == null) { throw new LambdaException( "Sorry, that user does not exist", args, context); } // Updating user's password, but only if a new password was supplied by caller. if (!string.IsNullOrEmpty(password)) { authFile ["users"] [username] ["password"].Value = password; } // Updating user's role, if a new role was supplied by caller. if (role != null) { authFile ["users"] [username] ["role"].Value = role; } // Checking if caller wants to edit settings. if (args.Name == "p5.auth.users.edit") { // Removing old settings. authFile ["users"] [username].RemoveAll(ix => ix.Name != "password" && ix.Name != "role" && ix.Name != "salt"); // Adding all other specified objects to user. foreach (var idxNode in args.Children.Where(ix => ix.Name != "password" && ix.Name != "role" && ix.Name != "salt")) { authFile ["users"] [username].Add(idxNode.Clone()); } } }); }