From cca87dac91b0f635cc49fa895f9f688682e5f1c2 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 26 Sep 2016 13:51:15 +0900 Subject: [PATCH 4/8] Refactor decision-making of password encryption into a single routine This routine was duplicated for CREATE ROLE and ALTER ROLE, and while there is little gain by doing it now if there is only plain password and md5-encryption support, this eases the decision-making regarding if and how a password needs to be encrypted if there are more protocols supported, like SCRAM. --- src/backend/commands/user.c | 84 ++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index adc6b99..7f396c9 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -55,6 +55,8 @@ static void AddRoleMems(const char *rolename, Oid roleid, static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt); +static char *encrypt_password(char *passwd, char *rolname, + int passwd_type); /* Check if current user has createrole privileges */ @@ -64,6 +66,48 @@ have_createrole_privilege(void) return has_createrole_privilege(GetUserId()); } +/* + * Encrypt a password if necessary for insertion in pg_authid. + * + * If a password is found as already MD5-encrypted, no error is raised + * to ease the dump and reload of such data. Returns a palloc'ed string + * holding the encrypted password. + */ +static char * +encrypt_password(char *password, char *rolname, int passwd_type) +{ + char *res; + + Assert(password != NULL); + + /* + * If a password is already identified as MD5-encrypted, it is used + * as such. If the password given is not encrypted, adapt it depending + * on the type wanted by the caller of this routine. + */ + if (isMD5(password)) + res = pstrdup(password); + else + { + switch (passwd_type) + { + case PASSWORD_TYPE_PLAINTEXT: + res = pstrdup(password); + break; + case PASSWORD_TYPE_MD5: + res = (char *) palloc(MD5_PASSWD_LEN + 1); + if (!pg_md5_encrypt(password, rolname, + strlen(rolname), + res)) + elog(ERROR, "password encryption failed"); + break; + default: + Assert(0); /* should not come here */ + } + } + + return res; +} /* * CREATE ROLE @@ -81,7 +125,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) ListCell *option; char *password = NULL; /* user password */ int password_type = Password_encryption; - char encrypted_password[MD5_PASSWD_LEN + 1]; + char *encrypted_passwd; bool issuper = false; /* Make the user a superuser? */ bool inherit = true; /* Auto inherit privileges? */ bool createrole = false; /* Can this user create roles? */ @@ -393,17 +437,13 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) if (password) { - if (password_type == PASSWORD_TYPE_PLAINTEXT || isMD5(password)) - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(password); - else - { - if (!pg_md5_encrypt(password, stmt->role, strlen(stmt->role), - encrypted_password)) - elog(ERROR, "password encryption failed"); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(encrypted_password); - } + encrypted_passwd = encrypt_password(password, + stmt->role, + password_type); + + new_record[Anum_pg_authid_rolpassword - 1] = + CStringGetTextDatum(encrypted_passwd); + pfree(encrypted_passwd); } else new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; @@ -506,7 +546,7 @@ AlterRole(AlterRoleStmt *stmt) char *rolename = NULL; char *password = NULL; /* user password */ int password_type = Password_encryption; - char encrypted_password[MD5_PASSWD_LEN + 1]; + char *encrypted_passwd; int issuper = -1; /* Make the user a superuser? */ int inherit = -1; /* Auto inherit privileges? */ int createrole = -1; /* Can this user create roles? */ @@ -804,18 +844,14 @@ AlterRole(AlterRoleStmt *stmt) /* password */ if (password) { - if (password_type == PASSWORD_TYPE_PLAINTEXT || isMD5(password)) - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(password); - else - { - if (!pg_md5_encrypt(password, rolename, strlen(rolename), - encrypted_password)) - elog(ERROR, "password encryption failed"); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(encrypted_password); - } + encrypted_passwd = encrypt_password(password, + rolename, + password_type); + + new_record[Anum_pg_authid_rolpassword - 1] = + CStringGetTextDatum(encrypted_passwd); new_record_repl[Anum_pg_authid_rolpassword - 1] = true; + pfree(encrypted_passwd); } /* unset password */ -- 2.10.1