Mercurial > pidgin
comparison src/protocols/yahoo/crypt.c @ 10684:72a5babfa8b4
[gaim-migrate @ 12231]
the cipher api that grim has been working on for ages is finally done!! big
congrats and thanks to him!!
lots of modified files in this commit. it builds here.
moved the md5 files to src/protocols/oscar so that it continues to depend
on nothing in gaim. everything else uses the new centralized cipher api.
I'm not sure if src/md5.* needs to be removed or not, so I left it there.
someone let me know or do it directly.
someone check if these need to be added to potfiles.in
and let there be much rejoicing!
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Fri, 11 Mar 2005 13:05:31 +0000 |
| parents | e46efd264489 |
| children | b256ce6b85b8 |
comparison
equal
deleted
inserted
replaced
| 10683:e11f3e1599d4 | 10684:72a5babfa8b4 |
|---|---|
| 24 | 24 |
| 25 #include <string.h> | 25 #include <string.h> |
| 26 #include <stdlib.h> | 26 #include <stdlib.h> |
| 27 #include <glib.h> | 27 #include <glib.h> |
| 28 | 28 |
| 29 #include "md5.h" | 29 #include "cipher.h" |
| 30 | 30 |
| 31 /* Define our magic string to mark salt for MD5 "encryption" | 31 /* Define our magic string to mark salt for MD5 "encryption" |
| 32 replacement. This is meant to be the same as for other MD5 based | 32 replacement. This is meant to be the same as for other MD5 based |
| 33 encryption implementations. */ | 33 encryption implementations. */ |
| 34 static const char md5_salt_prefix[] = "$1$"; | 34 static const char md5_salt_prefix[] = "$1$"; |
| 37 static const char b64t[64] = | 37 static const char b64t[64] = |
| 38 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | 38 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
| 39 | 39 |
| 40 char *yahoo_crypt(const char *key, const char *salt) | 40 char *yahoo_crypt(const char *key, const char *salt) |
| 41 { | 41 { |
| 42 GaimCipher *cipher; | |
| 43 GaimCipherContext *context1, *context2; | |
| 44 guint8 digest[16]; | |
| 42 static char *buffer = NULL; | 45 static char *buffer = NULL; |
| 43 static int buflen = 0; | 46 static int buflen = 0; |
| 44 int needed = 3 + strlen (salt) + 1 + 26 + 1; | 47 int needed = 3 + strlen (salt) + 1 + 26 + 1; |
| 45 | 48 |
| 46 md5_byte_t alt_result[16]; | |
| 47 md5_state_t ctx; | |
| 48 md5_state_t alt_ctx; | |
| 49 size_t salt_len; | 49 size_t salt_len; |
| 50 size_t key_len; | 50 size_t key_len; |
| 51 size_t cnt; | 51 size_t cnt; |
| 52 char *cp; | 52 char *cp; |
| 53 | 53 |
| 55 buflen = needed; | 55 buflen = needed; |
| 56 if ((buffer = g_realloc(buffer, buflen)) == NULL) | 56 if ((buffer = g_realloc(buffer, buflen)) == NULL) |
| 57 return NULL; | 57 return NULL; |
| 58 } | 58 } |
| 59 | 59 |
| 60 cipher = gaim_ciphers_find_cipher("md5"); | |
| 61 context1 = gaim_cipher_context_new(cipher, NULL); | |
| 62 context2 = gaim_cipher_context_new(cipher, NULL); | |
| 63 | |
| 60 /* Find beginning of salt string. The prefix should normally always | 64 /* Find beginning of salt string. The prefix should normally always |
| 61 be present. Just in case it is not. */ | 65 * be present. Just in case it is not. |
| 66 */ | |
| 62 if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) | 67 if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) |
| 63 /* Skip salt prefix. */ | 68 /* Skip salt prefix. */ |
| 64 salt += sizeof (md5_salt_prefix) - 1; | 69 salt += sizeof (md5_salt_prefix) - 1; |
| 65 | 70 |
| 66 salt_len = MIN (strcspn (salt, "$"), 8); | 71 salt_len = MIN (strcspn (salt, "$"), 8); |
| 67 key_len = strlen (key); | 72 key_len = strlen (key); |
| 68 | 73 |
| 69 /* Prepare for the real work. */ | |
| 70 md5_init(&ctx); | |
| 71 | |
| 72 /* Add the key string. */ | 74 /* Add the key string. */ |
| 73 md5_append(&ctx, key, key_len); | 75 gaim_cipher_context_append(context1, key, key_len); |
| 74 | 76 |
| 75 /* Because the SALT argument need not always have the salt prefix we | 77 /* Because the SALT argument need not always have the salt prefix we |
| 76 add it separately. */ | 78 * add it separately. |
| 77 md5_append(&ctx, md5_salt_prefix, sizeof (md5_salt_prefix) - 1); | 79 */ |
| 80 gaim_cipher_context_append(context1, md5_salt_prefix, | |
| 81 sizeof(md5_salt_prefix) - 1); | |
| 78 | 82 |
| 79 /* The last part is the salt string. This must be at most 8 | 83 /* The last part is the salt string. This must be at most 8 |
| 80 characters and it ends at the first `$' character (for | 84 * characters and it ends at the first `$' character (for |
| 81 compatibility which existing solutions). */ | 85 * compatibility which existing solutions). |
| 82 md5_append(&ctx, salt, salt_len); | 86 */ |
| 87 gaim_cipher_context_append(context1, salt, salt_len); | |
| 83 | 88 |
| 84 /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The | 89 /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The |
| 85 final result will be added to the first context. */ | 90 * final result will be added to the first context. |
| 86 md5_init(&alt_ctx); | 91 */ |
| 87 | 92 |
| 88 /* Add key. */ | 93 /* Add key. */ |
| 89 md5_append(&alt_ctx, key, key_len); | 94 gaim_cipher_context_append(context2, key, key_len); |
| 90 | 95 |
| 91 /* Add salt. */ | 96 /* Add salt. */ |
| 92 md5_append(&alt_ctx, salt, salt_len); | 97 gaim_cipher_context_append(context2, salt, salt_len); |
| 93 | 98 |
| 94 /* Add key again. */ | 99 /* Add key again. */ |
| 95 md5_append(&alt_ctx, key, key_len); | 100 gaim_cipher_context_append(context2, key, key_len); |
| 96 | 101 |
| 97 /* Now get result of this (16 bytes) and add it to the other | 102 /* Now get result of this (16 bytes) and add it to the other context. */ |
| 98 context. */ | 103 gaim_cipher_context_digest(context2, NULL, digest); |
| 99 md5_finish(&alt_ctx, alt_result); | |
| 100 | 104 |
| 101 /* Add for any character in the key one byte of the alternate sum. */ | 105 /* Add for any character in the key one byte of the alternate sum. */ |
| 102 for (cnt = key_len; cnt > 16; cnt -= 16) | 106 for (cnt = key_len; cnt > 16; cnt -= 16) |
| 103 md5_append(&ctx, alt_result, 16); | 107 gaim_cipher_context_append(context1, digest, 16); |
| 104 md5_append(&ctx, alt_result, cnt); | 108 gaim_cipher_context_append(context1, digest, cnt); |
| 105 | 109 |
| 106 /* For the following code we need a NUL byte. */ | 110 /* For the following code we need a NUL byte. */ |
| 107 alt_result[0] = '\0'; | 111 digest[0] = '\0'; |
| 108 | 112 |
| 109 /* The original implementation now does something weird: for every 1 | 113 /* The original implementation now does something weird: for every 1 |
| 110 bit in the key the first 0 is added to the buffer, for every 0 | 114 * bit in the key the first 0 is added to the buffer, for every 0 |
| 111 bit the first character of the key. This does not seem to be | 115 * bit the first character of the key. This does not seem to be |
| 112 what was intended but we have to follow this to be compatible. */ | 116 * what was intended but we have to follow this to be compatible. |
| 117 */ | |
| 113 for (cnt = key_len; cnt > 0; cnt >>= 1) | 118 for (cnt = key_len; cnt > 0; cnt >>= 1) |
| 114 md5_append(&ctx, (cnt & 1) != 0 ? alt_result : (md5_byte_t *)key, 1); | 119 gaim_cipher_context_append(context1, |
| 120 (cnt & 1) != 0 ? digest : (guint8 *)key, 1); | |
| 115 | 121 |
| 116 /* Create intermediate result. */ | 122 /* Create intermediate result. */ |
| 117 md5_finish(&ctx, alt_result); | 123 gaim_cipher_context_digest(context1, NULL, digest); |
| 118 | 124 |
| 119 /* Now comes another weirdness. In fear of password crackers here | 125 /* Now comes another weirdness. In fear of password crackers here |
| 120 comes a quite long loop which just processes the output of the | 126 * comes a quite long loop which just processes the output of the |
| 121 previous round again. We cannot ignore this here. */ | 127 * previous round again. We cannot ignore this here. |
| 128 */ | |
| 122 for (cnt = 0; cnt < 1000; ++cnt) { | 129 for (cnt = 0; cnt < 1000; ++cnt) { |
| 123 /* New context. */ | 130 /* New context. */ |
| 124 md5_init(&ctx); | 131 gaim_cipher_context_reset(context2, NULL); |
| 125 | 132 |
| 126 /* Add key or last result. */ | 133 /* Add key or last result. */ |
| 127 if ((cnt & 1) != 0) | 134 if ((cnt & 1) != 0) |
| 128 md5_append(&ctx, key, key_len); | 135 gaim_cipher_context_append(context2, key, key_len); |
| 129 else | 136 else |
| 130 md5_append(&ctx, alt_result, 16); | 137 gaim_cipher_context_append(context2, digest, 16); |
| 131 | 138 |
| 132 /* Add salt for numbers not divisible by 3. */ | 139 /* Add salt for numbers not divisible by 3. */ |
| 133 if (cnt % 3 != 0) | 140 if (cnt % 3 != 0) |
| 134 md5_append(&ctx, salt, salt_len); | 141 gaim_cipher_context_append(context2, salt, salt_len); |
| 135 | 142 |
| 136 /* Add key for numbers not divisible by 7. */ | 143 /* Add key for numbers not divisible by 7. */ |
| 137 if (cnt % 7 != 0) | 144 if (cnt % 7 != 0) |
| 138 md5_append(&ctx, key, key_len); | 145 gaim_cipher_context_append(context2, key, key_len); |
| 139 | 146 |
| 140 /* Add key or last result. */ | 147 /* Add key or last result. */ |
| 141 if ((cnt & 1) != 0) | 148 if ((cnt & 1) != 0) |
| 142 md5_append(&ctx, alt_result, 16); | 149 gaim_cipher_context_append(context2, digest, 16); |
| 143 else | 150 else |
| 144 md5_append(&ctx, key, key_len); | 151 gaim_cipher_context_append(context2, key, key_len); |
| 145 | 152 |
| 146 /* Create intermediate result. */ | 153 /* Create intermediate result. */ |
| 147 md5_finish(&ctx, alt_result); | 154 gaim_cipher_context_digest(context2, NULL, digest); |
| 148 } | 155 } |
| 149 | 156 |
| 150 /* Now we can construct the result string. It consists of three | 157 /* Now we can construct the result string. It consists of three parts. */ |
| 151 parts. */ | |
| 152 | |
| 153 strncpy(buffer, md5_salt_prefix, MAX (0, buflen)); | 158 strncpy(buffer, md5_salt_prefix, MAX (0, buflen)); |
| 154 cp = buffer + strlen(buffer); | 159 cp = buffer + strlen(buffer); |
| 155 buflen -= sizeof (md5_salt_prefix); | 160 buflen -= sizeof (md5_salt_prefix); |
| 156 | 161 |
| 157 strncpy(cp, salt, MIN ((size_t) buflen, salt_len)); | 162 strncpy(cp, salt, MIN ((size_t) buflen, salt_len)); |
| 172 --buflen; \ | 177 --buflen; \ |
| 173 w >>= 6; \ | 178 w >>= 6; \ |
| 174 }\ | 179 }\ |
| 175 } while (0) | 180 } while (0) |
| 176 | 181 |
| 177 b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4); | 182 b64_from_24bit (digest[0], digest[6], digest[12], 4); |
| 178 b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4); | 183 b64_from_24bit (digest[1], digest[7], digest[13], 4); |
| 179 b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4); | 184 b64_from_24bit (digest[2], digest[8], digest[14], 4); |
| 180 b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4); | 185 b64_from_24bit (digest[3], digest[9], digest[15], 4); |
| 181 b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4); | 186 b64_from_24bit (digest[4], digest[10], digest[5], 4); |
| 182 b64_from_24bit (0, 0, alt_result[11], 2); | 187 b64_from_24bit (0, 0, digest[11], 2); |
| 183 if (buflen <= 0) { | 188 if (buflen <= 0) { |
| 184 g_free(buffer); | 189 g_free(buffer); |
| 185 buffer = NULL; | 190 buffer = NULL; |
| 186 } else | 191 } else |
| 187 *cp = '\0'; /* Terminate the string. */ | 192 *cp = '\0'; /* Terminate the string. */ |
| 188 | 193 |
| 189 /* Clear the buffer for the intermediate result so that people | 194 /* Clear the buffer for the intermediate result so that people |
| 190 attaching to processes or reading core dumps cannot get any | 195 * attaching to processes or reading core dumps cannot get any |
| 191 information. We do it in this way to clear correct_words[] | 196 * information. We do it in this way to clear correct_words[] |
| 192 inside the MD5 implementation as well. */ | 197 * inside the MD5 implementation as well. |
| 193 md5_init(&ctx); | 198 */ |
| 194 md5_finish(&ctx, alt_result); | 199 gaim_cipher_context_reset(context1, NULL); |
| 195 memset (&ctx, '\0', sizeof (ctx)); | 200 gaim_cipher_context_digest(context1, NULL, digest); |
| 196 memset (&alt_ctx, '\0', sizeof (alt_ctx)); | 201 gaim_cipher_context_destroy(context1); |
| 202 gaim_cipher_context_destroy(context2); | |
| 197 | 203 |
| 198 return buffer; | 204 return buffer; |
| 199 } | 205 } |
