Przeglądaj źródła

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
kris/onging/CECPQ3_patch15
Adam Langley 10 lat temu
rodzic
commit
4ac0b38cfc
1 zmienionych plików z 129 dodań i 122 usunięć
  1. +129
    -122
      crypto/x509/by_dir.c

+ 129
- 122
crypto/x509/by_dir.c Wyświetl plik

@@ -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:


Ładowanie…
Anuluj
Zapisz