On 2016/05/05 04:16, mike-...@ya.ru wrote:
> Seems it happens after this change:
> http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/crypt/crypt.c.diff?r1=1.26&r2=1.27

Yes.

https://mariadb.com/kb/en/mariadb/encrypt/:
> Encrypts str using the Unix crypt() system call

(sic: it's actually a library function not a system call).

This doesn't give any guarantees about encryption type though.
It just passes to the OS.

> If crypt() function entirely excluded from the system, the problem would be 
> detected on time
> and solved by linking with a third party library, as is done in other systems.

No, there's no fallback.

Yes we should disable this properly so that have_crypt is set
correctly. But the behaviour in that case would be the same as
you're seeing now.

As they say:

"If the have_crypt system variable is set to NO (because the crypt()
system call is not available), the ENCRYPT function will always
return NULL."

Here's the code.

sql/item_strfunc.cc:

2230 String *Item_func_encrypt::val_str(String *str)
2231 {
2232   DBUG_ASSERT(fixed == 1);
2233   String *res  =args[0]->val_str(str);
2234 
2235 #ifdef HAVE_CRYPT
2236   char salt[3],*salt_ptr;
2237   if ((null_value=args[0]->null_value))
2238     return 0;
2239   if (res->length() == 0)
2240     return make_empty_result();
2241   if (arg_count == 1)
2242   {                                     // generate random salt
2243     time_t timestamp=current_thd->query_start();
2244     salt[0] = bin_to_ascii( (ulong) timestamp & 0x3f);
2245     salt[1] = bin_to_ascii(( (ulong) timestamp >> 5) & 0x3f);
2246     salt[2] = 0;
2247     salt_ptr=salt;
2248   }
2249   else
2250   {                                     // obtain salt from the first two 
bytes
2251     String *salt_str=args[1]->val_str(&tmp_value);
2252     if ((null_value= (args[1]->null_value || salt_str->length() < 2)))
2253       return 0;
2254     salt_ptr= salt_str->c_ptr_safe();
2255   }
2256   mysql_mutex_lock(&LOCK_crypt);
2257   char *tmp= crypt(res->c_ptr_safe(),salt_ptr);
2258   if (!tmp)
2259   {
2260     mysql_mutex_unlock(&LOCK_crypt);
2261     null_value= 1;
2262     return 0;
2263   }
2264   str->set(tmp, (uint) strlen(tmp), &my_charset_bin);
2265   str->copy();
2266   mysql_mutex_unlock(&LOCK_crypt);
2267   return str;
2268 #else
2269   null_value=1;
2270   return 0;
2271 #endif  /* HAVE_CRYPT */
2272 }

> It comes to updating the OS and migration of existing databases.

MySQL/MariaDB's password storage support are *junk*. The only
native support for salted storage is this ancient crypt. No bcrypt,
scrypt, argon2. Even for things like salted SHA-2 you need to
construct it yourself.

I'd look at ways to handle this in the application instead where you
should have access to better tools. Migrate to proper password storage
in the database with a fallback in the application to handle unconverted
passwords. This can be done before upgrading the db server and
continue to function afterwards.

Best method is probably to bulk-update all the existing entries
so you store "newhash(salt+crypted)" then when someone tries
to log in, if "newhash(salt+password)" fails you can try
"newhash(salt+crypt(password))" and update the stored entry.
(http://www.lornajane.net/posts/2016/upgrade-better-passwords-php)

Reply via email to