summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc650
1 files changed, 327 insertions, 323 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 598ff153cad..c6c0c5f4ab3 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -51,7 +51,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length,
return (byte*) entry->key;
}
-#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+17)
+#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+USERNAME_LENGTH+1)
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex;
@@ -68,12 +68,54 @@ static ulong get_sort(uint count,...);
static void init_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user);
static bool update_user_table(THD *thd, const char *host, const char *user,
- const char *new_password);
+ const char *new_password, uint new_password_len);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
/*
+ Convert scrambled password to binary form, according to scramble type,
+ Binary form is stored in user.salt.
+*/
+
+static
+void
+set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
+{
+ if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ {
+ get_salt_from_password(acl_user->salt, password);
+ acl_user->salt_len= SCRAMBLE_LENGTH;
+ }
+ else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
+ {
+ get_salt_from_password_323((ulong *) acl_user->salt, password);
+ acl_user->salt_len= SCRAMBLE_LENGTH_323;
+ }
+ else
+ acl_user->salt_len= 0;
+}
+
+/*
+ This after_update function is used when user.password is less than
+ SCRAMBLE_LENGTH bytes.
+*/
+
+static void restrict_update_of_old_passwords_var(THD *thd,
+ enum_var_type var_type)
+{
+ if (var_type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.old_passwords= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.old_passwords= 1;
+}
+
+
+/*
Read grant privileges from the privilege tables in the 'mysql' database.
SYNOPSIS
@@ -114,8 +156,6 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
- /* Use passwords according to command line option */
- use_old_passwords= opt_old_passwords;
acl_cache->clear(1); // Clear locked hostname cache
thd->db= my_strdup("mysql",MYF(0));
@@ -172,103 +212,126 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100));
- if (table->field[2]->field_length == 8 &&
- protocol_version == PROTOCOL_VERSION)
+ if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- sql_print_error(
- "Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
- protocol_version=9; /* purecov: tested */
+ sql_print_error("Fatal error: mysql.user table is damaged or in "
+ "unsupported 3.20 format.");
+ goto end;
}
DBUG_PRINT("info",("user table fields: %d, password length: %d",
table->fields, table->field[2]->field_length));
- if (table->field[2]->field_length < 45 && !use_old_passwords)
+
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ {
+ if (opt_secure_auth)
+ {
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ sql_print_error("Fatal error: mysql.user table is in old format, "
+ "but server started with --secure-auth option.");
+ goto end;
+ }
+ sys_old_passwords.after_update= restrict_update_of_old_passwords_var;
+ if (global_system_variables.old_passwords)
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ else
+ {
+ global_system_variables.old_passwords= 1;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ sql_print_error("mysql.user table is not updated to new password format; "
+ "Disabling new password usage until "
+ "mysql_fix_privilege_tables is run");
+ }
+ thd->variables.old_passwords= 1;
+ }
+ else
{
- sql_print_error("mysql.user table is not updated to new password format; Disabling new password usage until mysql_fix_privilege_tables is run");
- use_old_passwords= 1;
+ sys_old_passwords.after_update= 0;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
}
allow_all_hosts=0;
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_USER user;
- uint length=0;
- update_hostname(&user.host,get_field(&mem, table->field[0]));
- user.user=get_field(&mem, table->field[1]);
- user.password=get_field(&mem, table->field[2]);
- if (user.password && (length=(uint) strlen(user.password)) == 8 &&
- protocol_version == PROTOCOL_VERSION)
- {
- sql_print_error(
- "Found old style password for user '%s'. Ignoring user. (You may want to restart mysqld using --old-protocol)",
- user.user ? user.user : ""); /* purecov: tested */
- }
- else /* non empty and not short passwords */
- {
- user.pversion=get_password_version(user.password);
- /* Only passwords of specific lengths depending on version are allowed */
- if ( (!user.pversion && length % 8) || (user.pversion && length!=45 ))
- {
- sql_print_error(
- "Found invalid password for user: '%s@%s'; Ignoring user",
- user.user ? user.user : "",
- user.host.hostname ? user.host.hostname : ""); /* purecov: tested */
- continue; /* purecov: tested */
+ update_hostname(&user.host, get_field(&mem, table->field[0]));
+ user.user= get_field(&mem, table->field[1]);
+ const char *password= get_field(&mem, table->field[2]);
+ uint password_len= password ? strlen(password) : 0;
+ set_user_salt(&user, password, password_len);
+ if (user.salt_len == 0 && password_len != 0)
+ {
+ switch (password_len) {
+ case 45: /* 4.1: to be removed */
+ sql_print_error("Found 4.1 style password for user '%s@%s'. "
+ "Ignoring user. "
+ "You should change password for this user.",
+ user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ break;
+ default:
+ sql_print_error("Found invalid password for user: '%s@%s'; "
+ "Ignoring user", user.user ? user.user : "",
+ user.host.hostname ? user.host.hostname : "");
+ break;
}
}
- get_salt_from_password(user.salt,user.password);
- user.access=get_access(table,3) & GLOBAL_ACLS;
- user.sort=get_sort(2,user.host.hostname,user.user);
- user.hostname_length= (user.host.hostname ?
- (uint) strlen(user.host.hostname) : 0);
- if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
- {
- char *ssl_type=get_field(&mem, table->field[24]);
- if (!ssl_type)
- user.ssl_type=SSL_TYPE_NONE;
- else if (!strcmp(ssl_type, "ANY"))
- user.ssl_type=SSL_TYPE_ANY;
- else if (!strcmp(ssl_type, "X509"))
- user.ssl_type=SSL_TYPE_X509;
- else /* !strcmp(ssl_type, "SPECIFIED") */
- user.ssl_type=SSL_TYPE_SPECIFIED;
-
- user.ssl_cipher= get_field(&mem, table->field[25]);
- user.x509_issuer= get_field(&mem, table->field[26]);
- user.x509_subject= get_field(&mem, table->field[27]);
-
- char *ptr = get_field(&mem, table->field[28]);
- user.user_resource.questions=atoi(ptr);
- ptr = get_field(&mem, table->field[29]);
- user.user_resource.updates=atoi(ptr);
- ptr = get_field(&mem, table->field[30]);
- user.user_resource.connections=atoi(ptr);
- if (user.user_resource.questions || user.user_resource.updates ||
- user.user_resource.connections)
- mqh_used=1;
- }
- else
+ else // password is correct
{
- user.ssl_type=SSL_TYPE_NONE;
- bzero(&(user.user_resource),sizeof(user.user_resource));
-#ifndef TO_BE_REMOVED
- if (table->fields <= 13)
- { // Without grant
- if (user.access & CREATE_ACL)
- user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+ user.access= get_access(table,3) & GLOBAL_ACLS;
+ user.sort= get_sort(2,user.host.hostname,user.user);
+ user.hostname_length= (user.host.hostname ?
+ (uint) strlen(user.host.hostname) : 0);
+ if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
+ {
+ char *ssl_type=get_field(&mem, table->field[24]);
+ if (!ssl_type)
+ user.ssl_type=SSL_TYPE_NONE;
+ else if (!strcmp(ssl_type, "ANY"))
+ user.ssl_type=SSL_TYPE_ANY;
+ else if (!strcmp(ssl_type, "X509"))
+ user.ssl_type=SSL_TYPE_X509;
+ else /* !strcmp(ssl_type, "SPECIFIED") */
+ user.ssl_type=SSL_TYPE_SPECIFIED;
+
+ user.ssl_cipher= get_field(&mem, table->field[25]);
+ user.x509_issuer= get_field(&mem, table->field[26]);
+ user.x509_subject= get_field(&mem, table->field[27]);
+
+ char *ptr = get_field(&mem, table->field[28]);
+ user.user_resource.questions=atoi(ptr);
+ ptr = get_field(&mem, table->field[29]);
+ user.user_resource.updates=atoi(ptr);
+ ptr = get_field(&mem, table->field[30]);
+ user.user_resource.connections=atoi(ptr);
+ if (user.user_resource.questions || user.user_resource.updates ||
+ user.user_resource.connections)
+ mqh_used=1;
}
- /* Convert old privileges */
- user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
- if (user.access & FILE_ACL)
- user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
- if (user.access & PROCESS_ACL)
- user.access|= SUPER_ACL | EXECUTE_ACL;
+ else
+ {
+ user.ssl_type=SSL_TYPE_NONE;
+ bzero(&(user.user_resource),sizeof(user.user_resource));
+#ifndef TO_BE_REMOVED
+ if (table->fields <= 13)
+ { // Without grant
+ if (user.access & CREATE_ACL)
+ user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+ }
+ /* Convert old privileges */
+ user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
+ if (user.access & FILE_ACL)
+ user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
+ if (user.access & PROCESS_ACL)
+ user.access|= SUPER_ACL | EXECUTE_ACL;
#endif
+ }
+ VOID(push_dynamic(&acl_users,(gptr) &user));
+ if (!user.host.hostname || user.host.hostname[0] == wild_many &&
+ !user.host.hostname[1])
+ allow_all_hosts=1; // Anyone can connect
}
- VOID(push_dynamic(&acl_users,(gptr) &user));
- if (!user.host.hostname || user.host.hostname[0] == wild_many &&
- !user.host.hostname[1])
- allow_all_hosts=1; // Anyone can connect
}
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare);
@@ -462,135 +525,105 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
/*
- Prepare crypted scramble to be sent to the client
-*/
+ Seek ACL entry for a user, check password, SSL cypher, and if
+ everything is OK, update THD user data and USER_RESOURCES struct.
-void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
-{
- /* Binary password format to be used for generation*/
- char bin_password[SCRAMBLE41_LENGTH];
- /* Generate new long scramble for the thread */
- create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
- thd->scramble[SCRAMBLE41_LENGTH]=0;
- /* Get binary form, First 4 bytes of prepared scramble is salt */
- get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
- (unsigned char*) bin_password);
- /* Store "*" as identifier for old passwords */
- if (!acl_user->pversion)
- prepared_scramble[0]='*';
- /* Finally encrypt password to get prepared scramble */
- password_crypt(thd->scramble, prepared_scramble+4, bin_password,
- SCRAMBLE41_LENGTH);
-}
-
-
-/*
- Get master privilges for user (priviliges for all tables).
- Required before connecting to MySQL
-
- As we have 2 stage handshake now we cache user not to lookup
- it second time. At the second stage we do not lookup user in case
- we already know it;
+ IMPLEMENTATION
+ This function does not check if the user has any sensible privileges:
+ only user's existence and validity is checked.
+ Note, that entire operation is protected by acl_cache_lock.
+ SYNOPSIS
+ acl_getroot()
+ thd thread handle. If all checks are OK,
+ thd->priv_user, thd->master_access are updated.
+ thd->host, thd->ip, thd->user are used for checks.
+ mqh user resources; on success mqh is reset, else
+ unchanged
+ passwd scrambled & crypted password, recieved from client
+ (to check): thd->scramble or thd->scramble_323 is
+ used to decrypt passwd, so they must contain
+ original random string,
+ passwd_len length of passwd, must be one of 0, 8,
+ SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
+ 'thd' and 'mqh' are updated on success; other params are IN.
+
+ RETURN VALUE
+ 0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
+ updated
+ 1 user not found or authentification failure
+ 2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
+ -1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
*/
-ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *message,char **priv_user,
- char *priv_host, bool old_ver, USER_RESOURCES *mqh,
- char *prepared_scramble, uint *cur_priv_version,
- ACL_USER **cached_user)
+int acl_getroot(THD *thd, USER_RESOURCES *mqh,
+ const char *passwd, uint passwd_len)
{
- ulong user_access=NO_ACCESS;
- *priv_user= (char*) user;
- bool password_correct= 0;
- int stage= (*cached_user != NULL); /* NULL passed as first stage */
- ACL_USER *acl_user= NULL;
DBUG_ENTER("acl_getroot");
- bzero(mqh,sizeof(USER_RESOURCES));
if (!initialized)
{
- // If no data allow anything
- DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */
+ /*
+ here if mysqld's been started with --skip-grant-tables option.
+ */
+ thd->priv_user= (char *) ""; // privileges for
+ *thd->priv_host= '\0'; // the user are unknown
+ thd->master_access= ~NO_ACCESS; // everything is allowed
+ bzero(mqh, sizeof(*mqh));
+ DBUG_RETURN(0);
}
+
+ int res= 1;
+
VOID(pthread_mutex_lock(&acl_cache->lock));
/*
- Get possible access from user_list. This is or'ed to others not
- fully specified
-
- If we have cached user use it, in other case look it up.
+ Find acl entry in user database. Note, that find_acl_user is not the same,
+ because it doesn't take into account the case when user is not empty,
+ but acl_user->user is empty
*/
- if (stage && (*cur_priv_version == priv_version))
- acl_user= *cached_user;
- else
+ ACL_USER *acl_user= 0;
+ for (uint i=0 ; i < acl_users.elements ; i++)
{
- for (uint i=0 ; i < acl_users.elements ; i++)
+ ACL_USER *user_i = dynamic_element(&acl_users,i,ACL_USER*);
+ if (!user_i->user || !strcmp(thd->user, user_i->user))
{
- ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*);
- if (!acl_user_search->user || !strcmp(user,acl_user_search->user))
+ if (compare_hostname(&user_i->host, thd->host, thd->ip))
{
- if (compare_hostname(&acl_user_search->host,host,ip))
+ /* check password: it should be empty or valid */
+ if (passwd_len == user_i->salt_len)
{
- /* Found mathing user */
- acl_user= acl_user_search;
- /* Store it as a cache */
- *cached_user= acl_user;
- *cur_priv_version= priv_version;
- break;
+ if (user_i->salt_len == 0 ||
+ user_i->salt_len == SCRAMBLE_LENGTH &&
+ check_scramble(passwd, thd->scramble, user_i->salt) == 0 ||
+ check_scramble_323(passwd, thd->scramble,
+ (ulong *) user_i->salt) == 0)
+ {
+ acl_user= user_i;
+ res= 0;
+ }
}
+ else if (passwd_len == SCRAMBLE_LENGTH &&
+ user_i->salt_len == SCRAMBLE_LENGTH_323)
+ res= -1;
+ else if (passwd_len == SCRAMBLE_LENGTH_323 &&
+ user_i->salt_len == SCRAMBLE_LENGTH)
+ res= 2;
+ /* linear search complete: */
+ break;
}
}
}
-
- /* Now we have acl_user found and may start our checks */
+ /*
+ This was moved to separate tree because of heavy HAVE_OPENSSL case.
+ If acl_user is not null, res is 0.
+ */
if (acl_user)
{
- /* Password should present for both or absend for both */
- if (!acl_user->password && !*password)
- password_correct=1;
- else if (!acl_user->password || !*password)
- {
- *cached_user= 0; // Impossible to connect
- }
- else
- {
- /* New version password is checked differently */
- if (acl_user->pversion)
- {
- if (stage) /* We check password only on the second stage */
- {
- if (!validate_password(password,message,acl_user->salt))
- password_correct=1;
- }
- else /* First stage - just prepare scramble */
- prepare_scramble(thd,acl_user,prepared_scramble);
- }
- /* Old way to check password */
- else
- {
- /* Checking the scramble at any stage. First - old clients */
- if (!check_scramble(password,message,acl_user->salt,
- (my_bool) old_ver))
- password_correct=1;
- else if (!stage) /* Here if password incorrect */
- {
- /* At the first stage - prepare scramble */
- prepare_scramble(thd,acl_user,prepared_scramble);
- }
- }
- }
- }
-
- /* If user not found password_correct will also be zero */
- if (!password_correct)
- goto unlock_and_exit;
-
- /* OK. User found and password checked continue validation */
-
- {
+ /* OK. User found and password checked continue validation */
+ thd->master_access= NO_ACCESS;
Vio *vio=thd->net.vio;
/*
At this point we know that user is allowed to connect
@@ -601,48 +634,48 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
switch (acl_user->ssl_type) {
case SSL_TYPE_NOT_SPECIFIED: // Impossible
case SSL_TYPE_NONE: /* SSL is not required to connect */
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
break;
#ifdef HAVE_OPENSSL
case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
if (vio_type(vio) == VIO_TYPE_SSL)
- user_access=acl_user->access;
+ thd->master_access= acl_user->access;
break;
case SSL_TYPE_X509: /* Client should have any valid certificate. */
/*
- Connections with non-valid certificates are dropped already
- in sslaccept() anyway, so we do not check validity here.
-
- We need to check for absence of SSL because without SSL
- we should reject connection.
+ Connections with non-valid certificates are dropped already
+ in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
*/
- if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_))
- user_access=acl_user->access;
+ if (vio_type(vio) == VIO_TYPE_SSL &&
+ SSL_get_peer_certificate(vio->ssl_))
+ thd->master_access= acl_user->access;
break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
/*
- We do not check for absence of SSL because without SSL it does
- not pass all checks here anyway.
- If cipher name is specified, we compare it to actual cipher in
- use.
+ We do not check for absence of SSL because without SSL it does
+ not pass all checks here anyway.
+ If cipher name is specified, we compare it to actual cipher in
+ use.
*/
if (vio_type(vio) != VIO_TYPE_SSL)
- break;
+ break;
if (acl_user->ssl_cipher)
{
- DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
- acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
- user_access=acl_user->access;
- else
- {
- if (global_system_variables.log_warnings)
- sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
- acl_user->ssl_cipher,
- SSL_get_cipher(vio->ssl_));
- user_access=NO_ACCESS;
- break;
- }
+ DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
+ acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)));
+ if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
+ thd->master_access= acl_user->access;
+ else
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 ciphers mismatch: should be '%s'"
+ "but is '%s'", acl_user->ssl_cipher,
+ SSL_get_cipher(vio->ssl_));
+ break;
+ }
}
/* Prepare certificate (if exists) */
DBUG_PRINT("info",("checkpoint 1"));
@@ -651,64 +684,58 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
/* If X509 issuer is speified, we check it... */
if (acl_user->x509_issuer)
{
- DBUG_PRINT("info",("checkpoint 3"));
- char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
- acl_user->x509_issuer, ptr));
- if (strcmp(acl_user->x509_issuer, ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'",
- acl_user->x509_issuer, ptr);
- user_access=NO_ACCESS;
- free(ptr);
- break;
- }
- user_access=acl_user->access;
- free(ptr);
+ DBUG_PRINT("info",("checkpoint 3"));
+ char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
+ acl_user->x509_issuer, ptr));
+ if (strcmp(acl_user->x509_issuer, ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 issuer mismatch: should be '%s' "
+ "but is '%s'", acl_user->x509_issuer, ptr);
+ free(ptr);
+ break;
+ }
+ thd->master_access=acl_user->access;
+ free(ptr);
}
DBUG_PRINT("info",("checkpoint 4"));
/* X509 subject is specified, we check it .. */
if (acl_user->x509_subject)
{
- char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
- acl_user->x509_subject, ptr));
- if (strcmp(acl_user->x509_subject,ptr))
- {
- if (global_system_variables.log_warnings)
- sql_print_error("X509 subject mismatch: '%s' vs '%s'",
- acl_user->x509_subject, ptr);
- user_access=NO_ACCESS;
- }
- else
- user_access=acl_user->access;
- free(ptr);
+ char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
+ DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
+ acl_user->x509_subject, ptr));
+ if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 subject mismatch: '%s' vs '%s'",
+ acl_user->x509_subject, ptr);
+ }
+ else
+ thd->master_access= acl_user->access;
+ free(ptr);
}
break;
-#else /* HAVE_OPENSSL */
- default:
+#else /* HAVE_OPENSSL */
+ default:
/*
- If we don't have SSL but SSL is required for this user the
- authentication should fail.
- */
- break;
+ If we don't have SSL but SSL is required for this user the
+ authentication should fail.
+ */
+ thd->master_access= acl_user->access;
#endif /* HAVE_OPENSSL */
}
- }
-
- *mqh=acl_user->user_resource;
- if (!acl_user->user)
- *priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
-
- if (acl_user->host.hostname)
- strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME);
- else
- *priv_host= 0;
+ thd->priv_user= acl_user->user ? thd->user : (char *) "";
+ *mqh= acl_user->user_resource;
-unlock_and_exit:
+ if (acl_user->host.hostname)
+ strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *thd->priv_host= 0;
+ }
VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(user_access);
+ DBUG_RETURN(res);
}
@@ -719,8 +746,9 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
return (byte*) buff->host.hostname;
}
+
static void acl_update_user(const char *user, const char *host,
- const char *password,
+ const char *password, uint password_len,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
@@ -756,20 +784,9 @@ static void acl_update_user(const char *user, const char *host,
acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0);
}
- if (password)
- {
- if (!password[0]) /* If password is empty set it to null */
- {
- acl_user->password=0;
- acl_user->pversion=0; // just initialize
- }
- else
- {
- acl_user->password=(char*) ""; // Just point at something
- get_salt_from_password(acl_user->salt,password);
- acl_user->pversion=get_password_version(acl_user->password);
- }
- }
+
+ set_user_salt(acl_user, password, password_len);
+ /* search complete: */
break;
}
}
@@ -778,7 +795,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host,
- const char *password,
+ const char *password, uint password_len,
enum SSL_type ssl_type,
const char *ssl_cipher,
const char *x509_issuer,
@@ -789,7 +806,6 @@ static void acl_insert_user(const char *user, const char *host,
ACL_USER acl_user;
acl_user.user=strdup_root(&mem,user);
update_hostname(&acl_user.host,strdup_root(&mem,host));
- acl_user.password=0;
acl_user.access=privileges;
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -799,12 +815,8 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0;
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
- if (password)
- {
- acl_user.password=(char*) ""; // Just point at something
- get_salt_from_password(acl_user.salt,password);
- acl_user.pversion=get_password_version(password);
- }
+
+ set_user_salt(&acl_user, password, password_len);
VOID(push_dynamic(&acl_users,(gptr) &acl_user));
if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many
@@ -1141,7 +1153,6 @@ bool check_change_password(THD *thd, const char *host, const char *user)
bool change_password(THD *thd, const char *host, const char *user,
char *new_password)
{
- uint length=0;
DBUG_ENTER("change_password");
DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
host,user,new_password));
@@ -1150,37 +1161,27 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user))
DBUG_RETURN(1);
- /*
- password should always be 0,16 or 45 chars;
- Simple hack to avoid cracking
- */
- length=(uint) strlen(new_password);
- if (length != 45)
- new_password[length & 16]=0;
-
VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user;
- if (!(acl_user= find_acl_user(host,user)))
+ if (!(acl_user= find_acl_user(host, user)))
{
- send_error(thd, ER_PASSWORD_NO_MATCH);
VOID(pthread_mutex_unlock(&acl_cache->lock));
+ send_error(thd, ER_PASSWORD_NO_MATCH);
DBUG_RETURN(1);
}
+ /* update loaded acl entry: */
+ uint new_password_len= new_password ? strlen(new_password) : 0;
+ set_user_salt(acl_user, new_password, new_password_len);
+
if (update_user_table(thd,
acl_user->host.hostname ? acl_user->host.hostname : "",
acl_user->user ? acl_user->user : "",
- new_password))
+ new_password, new_password_len))
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
send_error(thd,0); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
- get_salt_from_password(acl_user->salt,new_password);
- acl_user->pversion=get_password_version(new_password);
- if (!new_password[0])
- acl_user->password=0;
- else
- acl_user->password=(char*) ""; // Point at something
acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock));
@@ -1216,7 +1217,7 @@ find_acl_user(const char *host, const char *user)
if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user))
{
- if (compare_hostname(&(acl_user->host),host,host))
+ if (compare_hostname(&acl_user->host,host,host))
{
DBUG_RETURN(acl_user);
}
@@ -1286,7 +1287,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
****************************************************************************/
static bool update_user_table(THD *thd, const char *host, const char *user,
- const char *new_password)
+ const char *new_password, uint new_password_len)
{
TABLE_LIST tables;
TABLE *table;
@@ -1310,7 +1311,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- table->field[2]->store(new_password,(uint) strlen(new_password), &my_charset_latin1);
+ table->field[2]->store(new_password, new_password_len, &my_charset_latin1);
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@@ -1358,24 +1359,23 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
{
int error = -1;
bool old_row_exists=0;
- char *password,empty_string[1];
+ const char *password= "";
+ uint password_len= 0;
char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_user_table");
safe_mutex_assert_owner(&acl_cache->lock);
- password=empty_string;
- empty_string[0]=0;
-
if (combo.password.str && combo.password.str[0])
{
- if ((combo.password.length != HASH_PASSWORD_LENGTH)
- && combo.password.length != HASH_OLD_PASSWORD_LENGTH)
+ if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
+ combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
my_printf_error(ER_PASSWORD_NO_MATCH,
"Password hash should be a %d-digit hexadecimal number",
- MYF(0),HASH_PASSWORD_LENGTH);
+ MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1);
}
+ password_len= combo.password.length;
password=combo.password.str;
}
@@ -1400,17 +1400,20 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
goto end;
}
old_row_exists = 0;
- restore_record(table,default_values); // cp empty row from default_values
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
+ restore_record(table,default_values); // cp empty row from default_values
+ table->field[0]->store(combo.host.str,combo.host.length,
+ &my_charset_latin1);
+ table->field[1]->store(combo.user.str,combo.user.length,
+ &my_charset_latin1);
+ table->field[2]->store(password, password_len,
+ &my_charset_latin1);
}
else
{
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given
- table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1);
+ table->field[2]->store(password, password_len, &my_charset_latin1);
}
/* Update table columns with new privileges */
@@ -1507,10 +1510,8 @@ end:
if (!error)
{
acl_cache->clear(1); // Clear privilege cache
- if (!combo.password.str)
- password=0; // No password given on command
if (old_row_exists)
- acl_update_user(combo.user.str,combo.host.str,password,
+ acl_update_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type,
thd->lex.ssl_cipher,
thd->lex.x509_issuer,
@@ -1518,7 +1519,7 @@ end:
&thd->lex.mqh,
rights);
else
- acl_insert_user(combo.user.str,combo.host.str,password,
+ acl_insert_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type,
thd->lex.ssl_cipher,
thd->lex.x509_issuer,
@@ -2921,12 +2922,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length);
global.append ('\'');
- if (acl_user->password)
+ if (acl_user->salt_len)
{
- char passd_buff[HASH_PASSWORD_LENGTH+1];
- make_password_from_salt(passd_buff,acl_user->salt,acl_user->pversion);
+ char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
+ if (acl_user->salt_len == SCRAMBLE_LENGTH)
+ make_password_from_salt(passwd_buff, acl_user->salt);
+ else
+ make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
global.append(" IDENTIFIED BY PASSWORD '",25);
- global.append(passd_buff);
+ global.append(passwd_buff);
global.append('\'');
}
/* "show grants" SSL related stuff */