diff options
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 150 |
1 files changed, 101 insertions, 49 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 792c76ebc0d..c64fdc7a049 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -209,78 +209,84 @@ void Item_func_concat::fix_length_and_dec() Function des_encrypt() by tonu@spam.ee & monty Works only if compiled with OpenSSL library support. This returns a binary string where first character is - CHAR(128 | tail-length << 4 | key-number). - If one uses a string key key_number is 0. + CHAR(128 | key-number). + If one uses a string key key_number is 127. Encryption result is longer than original by formula: - new_length= (8-(original_length % 8))+1 + new_length= org_length + (8-(org_length % 8))+1 */ String *Item_func_des_encrypt::val_str(String *str) { #ifdef HAVE_OPENSSL - des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + des_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - struct st_des_keyschedule *keyschedule_ptr; const char *append_str="********"; uint key_number, res_length, tail; String *res= args[0]->val_str(str); if ((null_value=args[0]->null_value)) return 0; - if (res->length() == 0) + if ((res_length=res->length()) == 0) return &empty_string; if (arg_count == 1) - keyschedule_ptr= &des_keyschedule[key_number=des_default_key]; + { + /* Protect against someone doing FLUSH DES_KEY_FILE */ + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number=des_default_key]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + } else if (args[1]->result_type() == INT_RESULT) { key_number= (uint) args[1]->val_int(); if (key_number > 9) goto error; - keyschedule_ptr= &des_keyschedule[key_number]; + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); } else { - uint tail,res_length; String *keystr=args[1]->val_str(&tmp_value); if (!keystr) goto error; - key_number=15; // User key string + key_number=127; // User key string /* We make good 24-byte (168 bit) key from given plaintext key with MD5 */ - keyschedule_ptr= &keyschedule; + bzero((char*) &ivec,sizeof(ivec)); EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(), (int) keystr->length(), 1, (uchar*) &keyblock,ivec); - des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1); - des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2); - des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3); + des_set_key_unchecked(&keyblock.key1,keyschedule.ks1); + des_set_key_unchecked(&keyblock.key2,keyschedule.ks2); + des_set_key_unchecked(&keyblock.key3,keyschedule.ks3); } /* The problem: DES algorithm requires original data to be in 8-bytes - chunks. Missing bytes get filled with zeros and result of encryption - can be up to 7 bytes longer than original string. When decrypted, + chunks. Missing bytes get filled with '*'s and result of encryption + can be up to 8 bytes longer than original string. When decrypted, we do not know the size of original string :( - We add one byte with value 0x1..0x8 as the second byte to original - plaintext marking change of string length. + We add one byte with value 0x1..0x8 as the last byte of the padded + string marking change of string length. */ - tail= (7-(res->length()+7) % 8); // 0..7 marking extra length - res_length=res->length()+tail+1; - if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length)) + tail= (8-(res_length) % 8); // 1..8 marking extra length + res_length+=tail; + if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1)) goto error; - - tmp_value.length(res_length); - tmp_value[0]=(char) (128 | tail << 4 | key_number); + (*res)[res_length-1]=tail; // save extra length + tmp_value.length(res_length+1); + tmp_value[0]=(char) (128 | key_number); // Real encryption + bzero((char*) &ivec,sizeof(ivec)); des_ede3_cbc_encrypt((const uchar*) (res->ptr()), (uchar*) (tmp_value.ptr()+1), - res->length(), - keyschedule_ptr->ks1, - keyschedule_ptr->ks2, - keyschedule_ptr->ks3, + res_length, + keyschedule.ks1, + keyschedule.ks2, + keyschedule.ks3, &ivec, TRUE); return &tmp_value; @@ -295,24 +301,27 @@ String *Item_func_des_decrypt::val_str(String *str) { #ifdef HAVE_OPENSSL des_key_schedule ks1, ks2, ks3; - des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + des_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - struct st_des_keyschedule *keyschedule_ptr; String *res= args[0]->val_str(str); + uint length=res->length(),tail; if ((null_value=args[0]->null_value)) return 0; - if (res->length() < 9 || (res->length() % 8) != 1 || !((*res)[0] & 128)) + length=res->length(); + if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128)) return res; // Skip decryption if not encrypted if (arg_count == 1) // If automatic uncompression { - uint key_number=(uint) (*res)[0] & 15; + uint key_number=(uint) (*res)[0] & 127; // Check if automatic key and that we have privilege to uncompress using it if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9) goto error; - keyschedule_ptr= &des_keyschedule[key_number]; + VOID(pthread_mutex_lock(&LOCK_des_key_file)); + keyschedule= des_keyschedule[key_number]; + VOID(pthread_mutex_unlock(&LOCK_des_key_file)); } else { @@ -321,26 +330,30 @@ String *Item_func_des_decrypt::val_str(String *str) if (!keystr) goto error; - keyschedule_ptr= &keyschedule; + bzero((char*) &ivec,sizeof(ivec)); EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL, (uchar*) keystr->ptr(),(int) keystr->length(), 1,(uchar*) &keyblock,ivec); // Here we set all 64-bit keys (56 effective) one by one - des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1); - des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2); - des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3); + des_set_key_unchecked(&keyblock.key1,keyschedule.ks1); + des_set_key_unchecked(&keyblock.key2,keyschedule.ks2); + des_set_key_unchecked(&keyblock.key3,keyschedule.ks3); } - if (tmp_value.alloc(res->length()-1)) + if (tmp_value.alloc(length-1)) goto error; - /* Restore old length of key */ - tmp_value.length(res->length()-1-(((uchar) (*res)[0] >> 4) & 7)); + + bzero((char*) &ivec,sizeof(ivec)); des_ede3_cbc_encrypt((const uchar*) res->ptr()+1, (uchar*) (tmp_value.ptr()), - res->length()-1, - keyschedule_ptr->ks1, - keyschedule_ptr->ks2, - keyschedule_ptr->ks3, + length-1, + keyschedule.ks1, + keyschedule.ks2, + keyschedule.ks3, &ivec, FALSE); + /* Restore old length of key */ + if ((tail=(uint) (uchar) tmp_value[length-2]) > 8) + goto error; // Wrong key + tmp_value.length(length-1-tail); return &tmp_value; error: @@ -1274,9 +1287,9 @@ String *Item_func_soundex::val_str(String *str) if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - if (str_value.alloc(max(res->length(),4))) + if (tmp_value.alloc(max(res->length(),4))) return str; /* purecov: inspected */ - char *to= (char *) str_value.ptr(); + char *to= (char *) tmp_value.ptr(); char *from= (char *) res->ptr(), *end=from+res->length(); while (from != end && isspace(*from)) // Skip pre-space @@ -1300,11 +1313,11 @@ String *Item_func_soundex::val_str(String *str) last_ch = ch; // save code of last input letter } // for next double-letter check } - for (end=(char*) str_value.ptr()+4 ; to < end ; to++) + for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++) *to = '0'; *to=0; // end string - str_value.length((uint) (to-str_value.ptr())); - return &str_value; + tmp_value.length((uint) (to-tmp_value.ptr())); + return &tmp_value; } @@ -1759,6 +1772,45 @@ String *Item_func_conv::val_str(String *str) return str; } + +String *Item_func_hex::val_str(String *str) +{ + if (args[0]->result_type() != STRING_RESULT) + { + /* Return hex of unsigned longlong value */ + longlong dec= args[0]->val_int(); + char ans[65],*ptr; + if ((null_value= args[0]->null_value)) + return 0; + ptr= longlong2str(dec,ans,16); + if (str->copy(ans,(uint32) (ptr-ans))) + return &empty_string; // End of memory + return str; + } + + /* Convert given string to a hex string, character by character */ + String *res= args[0]->val_str(str); + const char *from, *end; + char *to; + if (!res || tmp_value.alloc(res->length()*2)) + { + null_value=1; + return 0; + } + null_value=0; + tmp_value.length(res->length()*2); + for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr(); + from != end ; + from++, to+=2) + { + uint tmp=(uint) (uchar) *from; + to[0]=_dig_vec[tmp >> 4]; + to[1]=_dig_vec[tmp & 15]; + } + return &tmp_value; +} + + #include <my_dir.h> // For my_stat String *Item_load_file::val_str(String *str) |