/*
**  Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers.
**    All rights reserved.
*/

#ifndef lint
static char dkim_tables_c_id[] = "@(#)$Id: dkim-tables.c,v 1.32 2007/11/28 18:49:49 msk Exp $";
#endif /* !lint */

/* system includes */
#include <sys/types.h>
#include <string.h>
#include <assert.h>

/* libsm includes */
#include <sm/gen.h>
#include <sm/types.h>
#include <sm/cdefs.h>

/* libdkim includes */
#include "dkim-tables.h"
#include "dkim.h"

/* lookup tables */
static struct chartable prv_keyparams[] =	/* key parameters */
{
	{ 'a',		DKIM_KEY_ALGORITHM },
	{ 'g',		DKIM_KEY_GRANULARITY },
	{ 'n',		DKIM_KEY_NOTES },
	{ 'p',		DKIM_KEY_DATA },
	{ 's',		DKIM_KEY_SERVICE },
	{ 't',		DKIM_KEY_FLAGS },
	{ 'v',		DKIM_KEY_VERSION },
	{ '\0',		-1 }
};
struct chartable *keyparams = prv_keyparams;

static struct nametable prv_policyflags[] =	/* policy flags */
{
	{ "y",		DKIM_PFLAG_TEST },
	{ "s",		DKIM_PFLAG_NOSUBDOMAIN },
	{ NULL,		-1 }
};
struct nametable *policyflags = prv_policyflags;

static struct nametable prv_keyflags[] =	/* policy flags */
{
	{ "y",		DKIM_SIGFLAG_TESTKEY },
	{ "s",		DKIM_SIGFLAG_NOSUBDOMAIN },
	{ NULL,		-1 }
};
struct nametable *keyflags = prv_keyflags;

static struct nametable prv_policyparams[] =	/* policy parameters */
{
	{ "dkim",	DKIM_PPARAM_POLICY },
	{ "handling",	DKIM_PPARAM_HANDLING },
	{ "r",		DKIM_PPARAM_REPORTADDR },
	{ "t",		DKIM_PPARAM_FLAGS },
	{ NULL,		-1 }
};
struct nametable *policyparams = prv_policyparams;

static struct nametable prv_policies[] =	/* policies */
{
	{ "unknown",	DKIM_POLICY_UNKNOWN },
	{ "all",	DKIM_POLICY_ALL },
	{ "strict",	DKIM_POLICY_STRICT },
	{ NULL,		-1 }
};
struct nametable *policies = prv_policies;

static struct nametable prv_handlings[] =	/* SSP recommended handling */
{
	{ "process",	DKIM_HANDLING_PROCESS },
	{ "deny",	DKIM_HANDLING_DENY },
	{ NULL,		-1 }
};
struct nametable *handlings = prv_handlings;

static struct nametable prv_policyresults[] =	/* policy results */
{
	{ "none",				DKIM_PRESULT_NONE },
	{ "domain does not exist",		DKIM_PRESULT_NXDOMAIN },
	{ "policy \"unknown\"",			DKIM_PRESULT_UNKNOWN },
	{ "top-level domain",			DKIM_PRESULT_TOPLEVEL },
	{ "parent domain check",		DKIM_PRESULT_PARENTOK },
	{ "policy test flag set",		DKIM_PRESULT_TESTFLAG },
	{ "policy \"all\" and valid signature",	DKIM_PRESULT_ALLVALIDSIG },
	{ "valid originator signature",		DKIM_PRESULT_VALIDOSIG },
	{ "policy check failed",		DKIM_PRESULT_POLICYERROR },
	{ NULL,					-1 }
};
struct nametable *policyresults = prv_policyresults;

static struct nametable prv_sigparams[] =	/* signature parameters */
{
	{ "a",		DKIM_PARAM_SIGNALG },
	{ "b",		DKIM_PARAM_SIGNATURE },
	{ "bh",		DKIM_PARAM_BODYHASH },
	{ "c",		DKIM_PARAM_CANONALG },
	{ "d",		DKIM_PARAM_DOMAIN },
	{ "h",		DKIM_PARAM_HDRLIST },
	{ "i",		DKIM_PARAM_IDENTITY },
	{ "l",		DKIM_PARAM_BODYLENGTH },
	{ "q",		DKIM_PARAM_QUERYMETHOD },
	{ "s",		DKIM_PARAM_SELECTOR },
	{ "t",		DKIM_PARAM_TIMESTAMP },
	{ "v",		DKIM_PARAM_VERSION },
	{ "x",		DKIM_PARAM_EXPIRATION },
	{ "z",		DKIM_PARAM_COPIEDHDRS },
	{ NULL,		-1 }
};
struct nametable *sigparams = prv_sigparams;

static struct nametable prv_algorithms[] =	/* signing algorithms */
{
	{ "rsa-sha1",	DKIM_SIGN_RSASHA1 },
#ifdef SHA256_DIGEST_LENGTH
	{ "rsa-sha256",	DKIM_SIGN_RSASHA256 },
#endif /* SHA256_DIGEST_LENGTH */
	{ NULL,		-1 },
};
struct nametable *algorithms = prv_algorithms;

static struct nametable prv_canonicalizations[] = /* canonicalizations */
{
	{ "simple",	DKIM_CANON_SIMPLE },
	{ "relaxed",	DKIM_CANON_RELAXED },
	{ NULL,		-1 },
};
struct nametable *canonicalizations = prv_canonicalizations;

static struct nametable prv_hashes[] =		/* hashes */
{
	{ "sha1",	DKIM_HASHTYPE_SHA1 },
#ifdef SHA256_DIGEST_LENGTH
	{ "sha256",	DKIM_HASHTYPE_SHA256 },
#endif /* SHA256_DIGEST_LENGTH */
	{ NULL,		-1 },
};
struct nametable *hashes = prv_hashes;

static struct nametable prv_keytypes[] =	/* key types */
{
	{ "rsa",	DKIM_KEYTYPE_RSA },
	{ NULL,		-1 },
};
struct nametable *keytypes = prv_keytypes;

static struct nametable prv_querytypes[] =	/* query types */
{
	{ "dns",	DKIM_QUERY_DNS },
	{ NULL,		-1 },
};
struct nametable *querytypes = prv_querytypes;

static struct nametable prv_results[] =		/* result codes */
{
	{ "Success",			DKIM_STAT_OK },
	{ "Bad signature",		DKIM_STAT_BADSIG },
	{ "No signature",		DKIM_STAT_NOSIG },
	{ "No key",			DKIM_STAT_NOKEY },
	{ "Unable to verify",		DKIM_STAT_CANTVRFY },
	{ "Syntax error",		DKIM_STAT_SYNTAX },
	{ "Resource unavailable",	DKIM_STAT_NORESOURCE },
	{ "Internal error",		DKIM_STAT_INTERNAL },
	{ "Revoked key",		DKIM_STAT_REVOKED },
	{ "Invalid parameter",		DKIM_STAT_INVALID },
	{ "Not implemented",		DKIM_STAT_NOTIMPLEMENT },
	{ "Key retrieval failed",	DKIM_STAT_KEYFAIL },
	{ "Reject requested",		DKIM_STAT_CBREJECT },
	{ "Invalid result",		DKIM_STAT_CBINVALID },
	{ "Try again later",		DKIM_STAT_CBTRYAGAIN },
	{ NULL,				-1 },
};
struct nametable *results = prv_results;

static struct nametable prv_settypes[] =	/* set types */
{
	{ "key",	DKIM_SETTYPE_KEY },
	{ "policy",	DKIM_SETTYPE_POLICY },
	{ "signature",	DKIM_SETTYPE_SIGNATURE },
	{ NULL,		-1 },
};
struct nametable *settypes = prv_settypes;

static struct nametable prv_sigerrors[] =	/* signature parsing errors */
{
	{ "no signature error", 		DKIM_SIGERROR_OK },
	{ "unsupported signature version",	DKIM_SIGERROR_VERSION },
	{ "invalid domain coverage",		DKIM_SIGERROR_DOMAIN },
	{ "signature expired",			DKIM_SIGERROR_EXPIRED },
	{ "signature timestamp in the future",	DKIM_SIGERROR_FUTURE },
	{ "signature timestamp order error",	DKIM_SIGERROR_TIMESTAMPS },
	{ "canonicalization missing",		DKIM_SIGERROR_MISSING_C },
	{ "invalid header canonicalization",	DKIM_SIGERROR_INVALID_HC },
	{ "invalid body canonicalization",	DKIM_SIGERROR_INVALID_BC },
	{ "signature algorithm missing",	DKIM_SIGERROR_MISSING_A },
	{ "signature algorithm invalid",	DKIM_SIGERROR_INVALID_A },
	{ "header list missing",		DKIM_SIGERROR_MISSING_H },
	{ "body length value invalid",		DKIM_SIGERROR_INVALID_L },
	{ "query method invalid",		DKIM_SIGERROR_INVALID_Q },
	{ "query option invalid",		DKIM_SIGERROR_INVALID_QO },
	{ "domain tag missing",			DKIM_SIGERROR_MISSING_D },
	{ "domain tag empty",			DKIM_SIGERROR_EMPTY_D },
	{ "selector tag missing",		DKIM_SIGERROR_MISSING_S },
	{ "selector tag empty",			DKIM_SIGERROR_EMPTY_S },
	{ "signature data missing",		DKIM_SIGERROR_MISSING_B },
	{ "signature data empty",		DKIM_SIGERROR_EMPTY_B },
	{ "signature data corrupt",		DKIM_SIGERROR_CORRUPT_B },
	{ "key not found in DNS",		DKIM_SIGERROR_NOKEY },
	{ "key DNS reply corrupt",		DKIM_SIGERROR_DNSSYNTAX },
	{ "key DNS query failed",		DKIM_SIGERROR_KEYFAIL },
	{ "body hash missing",			DKIM_SIGERROR_MISSING_BH },
	{ "body hash empty",			DKIM_SIGERROR_EMPTY_BH },
	{ "body hash corrupt",			DKIM_SIGERROR_CORRUPT_BH },
	{ "signature verification failed",	DKIM_SIGERROR_BADSIG },
	{ "unauthorized subdomain",		DKIM_SIGERROR_SUBDOMAIN },
	{ NULL,					-1 },
};
struct nametable *sigerrors = prv_sigerrors;

/* ===================================================================== */

/*
**  DKIM_CODE_TO_NAME -- translate a mnemonic code to its name
**
**  Parameters:
**  	tbl -- name table
**  	code -- code to translate
**
**  Return value:
**  	Pointer to the name matching the provided code, or NULL if not found.
*/

const char *
dkim_code_to_name(struct nametable *tbl, const int code)
{
	int c;

	assert(tbl != NULL);

	for (c = 0; ; c++)
	{
		if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL)
			return NULL;

		if (tbl[c].tbl_code == code)
			return tbl[c].tbl_name;
	}
}

/*
**  DKIM_NAME_TO_CODE -- translate a name to a mnemonic code
**
**  Parameters:
**  	tbl -- name table
**  	name -- name to translate
**
**  Return value:
**  	A mnemonic code matching the provided name, or -1 if not found.
*/

const int
dkim_name_to_code(struct nametable *tbl, const char *name)
{
	int c;

	assert(tbl != NULL);

	for (c = 0; ; c++)
	{
		if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL)
			return -1;

		if (strcasecmp(tbl[c].tbl_name, name) == 0)
			return tbl[c].tbl_code;
	}
}

/*
**  DKIM_CODE_TO_CHAR -- translate a mnemonic code to its matching character
**
**  Parameters:
**  	tbl -- name table
**  	code -- code to translate
**
**  Return value:
**  	Character representing the mnemonic code provided, or '\0' if
**  	not found.
*/

const int
dkim_code_to_char(struct chartable *tbl, const int code)
{
	int c;

	assert(tbl != NULL);

	for (c = 0; ; c++)
	{
		if (tbl[c].tbl_code == -1 && tbl[c].tbl_char == '\0')
			return '\0';

		if (tbl[c].tbl_code == code)
			return tbl[c].tbl_char;
	}
}

/*
**  DKIM_CODE_TO_CHAR -- translate a mnemonic code to its matching character
**
**  Parameters:
**  	tbl -- name table
**  	chr -- character to translate
**
**  Return value:
**  	Mnemonic representing the character code provided, or '\0' if
**  	not found.
*/

const int
dkim_char_to_code(struct chartable *tbl, const int chr)
{
	int c;

	assert(tbl != NULL);

	for (c = 0; ; c++)
	{
		if (tbl[c].tbl_code == -1 && tbl[c].tbl_char == '\0')
			return -1;

		if (tbl[c].tbl_char == chr)
			return tbl[c].tbl_code;
	}
}


syntax highlighted by Code2HTML, v. 0.9.1