/* crypto/x509/by_dir.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 *
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 *
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 *
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.] */

#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include <openssl/x509.h>

#include "../internal.h"


typedef struct lookup_dir_hashes_st
	{
	unsigned long hash;
	int suffix;
	} BY_DIR_HASH;

typedef struct lookup_dir_entry_st
	{
	char *dir;
	int dir_type;
	STACK_OF(BY_DIR_HASH) *hashes;
	} BY_DIR_ENTRY;

typedef struct lookup_dir_st
	{
	BUF_MEM *buffer;
	STACK_OF(BY_DIR_ENTRY) *dirs;
	} BY_DIR;

DECLARE_STACK_OF(BY_DIR_HASH)
DECLARE_STACK_OF(BY_DIR_ENTRY)

static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
	char **ret);
static int new_dir(X509_LOOKUP *lu);
static void free_dir(X509_LOOKUP *lu);
static int add_cert_dir(BY_DIR *ctx,const char *dir,int type);
static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name,
	X509_OBJECT *ret);
static X509_LOOKUP_METHOD x509_dir_lookup=
	{
	"Load certs from files in a directory",
	new_dir,		/* new */
	free_dir,		/* free */
	NULL, 			/* init */
	NULL,			/* shutdown */
	dir_ctrl,		/* ctrl */
	get_cert_by_subject,	/* get_by_subject */
	NULL,			/* get_by_issuer_serial */
	NULL,			/* get_by_fingerprint */
	NULL,			/* get_by_alias */
	};

X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
	{
	return(&x509_dir_lookup);
	}

static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
	     char **retp)
	{
	int ret=0;
	BY_DIR *ld;
	char *dir = NULL;

	ld=(BY_DIR *)ctx->method_data;

	switch (cmd)
		{
	case X509_L_ADD_DIR:
		if (argl == X509_FILETYPE_DEFAULT)
			{
			dir=(char *)getenv(X509_get_default_cert_dir_env());
			if (dir)
				ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
			else
				ret=add_cert_dir(ld,X509_get_default_cert_dir(),
					X509_FILETYPE_PEM);
			if (!ret)
				{
				OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR);
				}
			}
		else
			ret=add_cert_dir(ld,argp,(int)argl);
		break;
		}
	return(ret);
	}

static int new_dir(X509_LOOKUP *lu)
	{
	BY_DIR *a;

	if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
		return(0);
	if ((a->buffer=BUF_MEM_new()) == NULL)
		{
		OPENSSL_free(a);
		return(0);
		}
	a->dirs=NULL;
	lu->method_data=(char *)a;
	return(1);
	}

static void by_dir_hash_free(BY_DIR_HASH *hash)
	{
	OPENSSL_free(hash);
	}

static int by_dir_hash_cmp(const BY_DIR_HASH **a,
			const BY_DIR_HASH **b)
	{
	if ((*a)->hash > (*b)->hash)
		return 1;
	if ((*a)->hash < (*b)->hash)
		return -1;
	return 0;
	}

static void by_dir_entry_free(BY_DIR_ENTRY *ent)
	{
	if (ent->dir)
		OPENSSL_free(ent->dir);
	if (ent->hashes)
		sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
	OPENSSL_free(ent);
	}

static void free_dir(X509_LOOKUP *lu)
	{
	BY_DIR *a;

	a=(BY_DIR *)lu->method_data;
	if (a->dirs != NULL)
		sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
	if (a->buffer != NULL)
		BUF_MEM_free(a->buffer);
	OPENSSL_free(a);
	}

static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
	{
	size_t j,len;
	const char *s,*ss,*p;

	if (dir == NULL || !*dir)
	    {
	    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY);
	    return 0;
	    }

	s=dir;
	p=s;
	do
		{
		if ((*p == ':') || (*p == '\0'))
			{
			BY_DIR_ENTRY *ent;
			ss=s;
			s=p+1;
			len=p-ss;
			if (len == 0) continue;
			for (j=0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++)
				{
				ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
				if (strlen(ent->dir) == len &&
				    strncmp(ent->dir,ss,len) == 0)
					break;
				}
			if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
				continue;
			if (ctx->dirs == NULL)
				{
				ctx->dirs = sk_BY_DIR_ENTRY_new_null();
				if (!ctx->dirs)
					{
					OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
					return 0;
					}
				}
			ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
			if (!ent)
				return 0;
			ent->dir_type = type;
			ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
			ent->dir = OPENSSL_malloc(len+1);
			if (!ent->dir || !ent->hashes)
				{
				by_dir_entry_free(ent);
				return 0;
				}
			strncpy(ent->dir,ss,len);
			ent->dir[len] = '\0';
			if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
				{
				by_dir_entry_free(ent);
				return 0;
				}
			}
		} while (*p++ != '\0');
	return 1;
	}

/* g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
 * objects. */
static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = CRYPTO_STATIC_MUTEX_INIT;

static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
	     X509_OBJECT *ret)
	{
	BY_DIR *ctx;
	union	{
		struct	{
			X509 st_x509;
			X509_CINF st_x509_cinf;
			} x509;
		struct	{
			X509_CRL st_crl;
			X509_CRL_INFO st_crl_info;
			} crl;
		} data;
	int ok=0;
	size_t i;
	int j,k;
	unsigned long h;
	unsigned long hash_array[2];
	int hash_index;
	BUF_MEM *b=NULL;
	X509_OBJECT stmp,*tmp;
	const char *postfix="";

	if (name == NULL) return(0);

	stmp.type=type;
	if (type == X509_LU_X509)
		{
		data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
		data.x509.st_x509_cinf.subject=name;
		stmp.data.x509= &data.x509.st_x509;
		postfix="";
		}
	else if (type == X509_LU_CRL)
		{
		data.crl.st_crl.crl= &data.crl.st_crl_info;
		data.crl.st_crl_info.issuer=name;
		stmp.data.crl= &data.crl.st_crl;
		postfix="r";
		}
	else
		{
		OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE);
		goto finish;
		}

	if ((b=BUF_MEM_new()) == NULL)
		{
		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
		goto finish;
		}
	
	ctx=(BY_DIR *)xl->method_data;

	hash_array[0]=X509_NAME_hash(name);
	hash_array[1]=X509_NAME_hash_old(name);
	for (hash_index=0; hash_index < 2; ++hash_index)
		{
		h=hash_array[hash_index];
		for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
			{
			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))
				{
				OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
				goto finish;
				}
			if (type == X509_LU_CRL && ent->hashes)
				{
				htmp.hash = h;
				CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock);
				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_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
				}
			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 = ':';
					}
				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)
						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_MUTEX_lock_write(&xl->store_ctx->objs_lock);
			tmp = NULL;
			if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
				tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx);
			}
			CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);


			/* If a CRL, update the last file suffix added for this */

			if (type == X509_LU_CRL)
				{
				CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
				/* 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));
					if (hent == NULL)
						{
						CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
						ok = 0;
						goto finish;
						}
					hent->hash = h;
					hent->suffix = k;
					if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
						{
						CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
						OPENSSL_free(hent);
						ok = 0;
						goto finish;
						}
					}
				else if (hent->suffix < k)
					hent->suffix = k;

				CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
				}

			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:
	if (b != NULL) BUF_MEM_free(b);
	return(ok);
	}
