diff options
author | Adam Langley <agl@chromium.org> | 2014-06-21 02:25:14 +0400 |
---|---|---|
committer | Adam Langley <agl@chromium.org> | 2014-06-21 02:31:01 +0400 |
commit | 4ac0b38cfc955373a0f0a939b9fb537a07fa8978 (patch) | |
tree | d9576d2ab7a52a0fe6c342c23dff3ef0ecff502f /crypto/x509 | |
parent | 3ffd70ec3692f577a947295152fb041ff4b8607b (diff) |
Try both old and new X.509 hashes.
Ensure the library can find the right files under /etc/ssl/certs when
running on older systems.
There are many symbolic links under /etc/ssl/certs created by using
hash of the PEM certificates in order for OpenSSL to find those
certificates. Openssl has a tool to help you create hash symbolic
links (tools/c_rehash). However newer versions of the library changed
the hash algorithm, which makes it unable to run properly on systems
that use the old /etc/ssl/certs layout (e.g. Ubuntu Lucid).
This patch gives a way to find a certificate according to its hash by
using both the old and new algorithms. http://crbug.com/111045 is used
to track this issue.
(Imported from Chromium:
http://src.chromium.org/viewvc/chrome/trunk/deps/third_party/openssl/patches.chromium/0003-x509_hash_name_algorithm_change.patch?revision=231571)
Change-Id: Idbc27aba7685c991f8b94cfea38cf4f3f4b38adc
Diffstat (limited to 'crypto/x509')
-rw-r--r-- | crypto/x509/by_dir.c | 251 |
1 files changed, 129 insertions, 122 deletions
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index 23877925..ecfb33c4 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -277,6 +277,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, int ok=0; int i,j,k; unsigned long h; + unsigned long hash_array[2]; + int hash_index; BUF_MEM *b=NULL; X509_OBJECT stmp,*tmp; const char *postfix=""; @@ -312,156 +314,161 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, ctx=(BY_DIR *)xl->method_data; - h=X509_NAME_hash(name); - for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) + hash_array[0]=X509_NAME_hash(name); + hash_array[1]=X509_NAME_hash_old(name); + for (hash_index=0; hash_index < 2; ++hash_index) { - BY_DIR_ENTRY *ent; - size_t idx; - BY_DIR_HASH htmp, *hent; - ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); - j=strlen(ent->dir)+1+8+6+1+1; - if (!BUF_MEM_grow(b,j)) + h=hash_array[hash_index]; + for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { - OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_MALLOC_FAILURE); - goto finish; - } - if (type == X509_LU_CRL && ent->hashes) - { - htmp.hash = h; - CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); - if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) + BY_DIR_ENTRY *ent; + size_t idx; + BY_DIR_HASH htmp, *hent; + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); + j=strlen(ent->dir)+1+8+6+1+1; + if (!BUF_MEM_grow(b,j)) { - hent = sk_BY_DIR_HASH_value(ent->hashes, idx); - k = hent->suffix; + OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_MALLOC_FAILURE); + goto finish; } - else + if (type == X509_LU_CRL && ent->hashes) { - hent = NULL; - k=0; - } - CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); - } - else - { - k = 0; - hent = NULL; - } - for (;;) - { - char c = '/'; -#ifdef OPENSSL_SYS_VMS - c = ent->dir[strlen(ent->dir)-1]; - if (c != ':' && c != '>' && c != ']') - { - /* If no separator is present, we assume the - directory specifier is a logical name, and - add a colon. We really should use better - VMS routines for merging things like this, - but this will do for now... - -- Richard Levitte */ - c = ':'; + htmp.hash = h; + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) + { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + k = hent->suffix; + } + else + { + hent = NULL; + k=0; + } + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); } else { - c = '\0'; - } -#endif - if (c == '\0') - { - /* This is special. When c == '\0', no - directory separator should be added. */ - BIO_snprintf(b->data,b->max, - "%s%08lx.%s%d",ent->dir,h, - postfix,k); + k = 0; + hent = NULL; } - else + for (;;) { - BIO_snprintf(b->data,b->max, - "%s%c%08lx.%s%d",ent->dir,c,h, - postfix,k); - } + char c = '/'; +#ifdef OPENSSL_SYS_VMS + c = ent->dir[strlen(ent->dir)-1]; + if (c != ':' && c != '>' && c != ']') + { + /* If no separator is present, we assume the + directory specifier is a logical name, and + add a colon. We really should use better + VMS routines for merging things like this, + but this will do for now... + -- Richard Levitte */ + c = ':'; + } + else + { + c = '\0'; + } +#endif + if (c == '\0') + { + /* This is special. When c == '\0', no + directory separator should be added. */ + BIO_snprintf(b->data,b->max, + "%s%08lx.%s%d",ent->dir,h, + postfix,k); + } + else + { + BIO_snprintf(b->data,b->max, + "%s%c%08lx.%s%d",ent->dir,c,h, + postfix,k); + } #ifndef OPENSSL_NO_POSIX_IO #ifdef _WIN32 #define stat _stat #endif - { - struct stat st; - if (stat(b->data,&st) < 0) - break; - } -#endif - /* found one. */ - if (type == X509_LU_X509) { - if ((X509_load_cert_file(xl,b->data, - ent->dir_type)) == 0) + struct stat st; + if (stat(b->data,&st) < 0) break; } - else if (type == X509_LU_CRL) - { - if ((X509_load_crl_file(xl,b->data, - ent->dir_type)) == 0) - break; +#endif + /* found one. */ + if (type == X509_LU_X509) + { + if ((X509_load_cert_file(xl,b->data, + ent->dir_type)) == 0) + break; + } + else if (type == X509_LU_CRL) + { + if ((X509_load_crl_file(xl,b->data, + ent->dir_type)) == 0) + break; + } + /* else case will caught higher up */ + k++; } - /* else case will caught higher up */ - k++; - } - /* we have added it to the cache so now pull - * it out again */ - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - tmp = NULL; - if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { - tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx); - } - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + /* we have added it to the cache so now pull + * it out again */ + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + tmp = NULL; + if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { + tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx); + } + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - /* If a CRL, update the last file suffix added for this */ + /* If a CRL, update the last file suffix added for this */ - if (type == X509_LU_CRL) - { - CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); - /* Look for entry again in case another thread added - * an entry first. - */ - if (!hent) - { - htmp.hash = h; - if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) - hent = sk_BY_DIR_HASH_value(ent->hashes, idx); - } - if (!hent) + if (type == X509_LU_CRL) { - hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); - hent->hash = h; - hent->suffix = k; - if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + /* Look for entry again in case another thread added + * an entry first. + */ + if (!hent) { - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - OPENSSL_free(hent); - ok = 0; - goto finish; + htmp.hash = h; + if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); } - } - else if (hent->suffix < k) - hent->suffix = k; + if (!hent) + { + hent = OPENSSL_malloc(sizeof(BY_DIR_HASH)); + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) + { + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + OPENSSL_free(hent); + ok = 0; + goto finish; + } + } + else if (hent->suffix < k) + hent->suffix = k; - CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); - } + } - if (tmp != NULL) - { - ok=1; - ret->type=tmp->type; - memcpy(&ret->data,&tmp->data,sizeof(ret->data)); - /* If we were going to up the reference count, - * we would need to do it on a perl 'type' - * basis */ - /* CRYPTO_add(&tmp->data.x509->references,1, - CRYPTO_LOCK_X509);*/ - goto finish; + if (tmp != NULL) + { + ok=1; + ret->type=tmp->type; + memcpy(&ret->data,&tmp->data,sizeof(ret->data)); + /* If we were going to up the reference count, + * we would need to do it on a perl 'type' + * basis */ + /* CRYPTO_add(&tmp->data.x509->references,1, + CRYPTO_LOCK_X509);*/ + goto finish; + } } } finish: |