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
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 2387792..ecfb33c 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -277,6 +277,8 @@
 	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 @@
 	
 	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;
+				}
+			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))
+					{
+					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
 				{
+				k = 0;
 				hent = NULL;
-				k=0;
 				}
-			CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
-			}
-		else
-			{
-			k = 0;
-			hent = NULL;
-			}
-		for (;;)
-			{
-			char c = '/';
+			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 = ':';
-				}
-			else
-				{
-				c = '\0';
-				}
+				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);
-				}
+				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;
-			}
+				{
+				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)
-					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++;
-			}
-
-		/* 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 (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)
-				{
-				hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
-				hent->hash = h;
-				hent->suffix = k;
-				if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
+				/* found one. */
+				if (type == X509_LU_X509)
 					{
-					CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
-					OPENSSL_free(hent);
-					ok = 0;
-					goto finish;
+					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 if (hent->suffix < k)
-				hent->suffix = 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);
 
-			}
 
-		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 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)
+					{
+					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);
+
+				}
+
+			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: