/*
 * Copyright (c) 2005, 2006 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-acc-0.c,v 1.8 2006/11/09 01:53:49 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/heap.h"
#include "sm/test.h"
#include "sm/maps.h"
#include "sm/map.h"
#include "sm/mapclasses.h"
#include "sm/hostname.h"
#include "sm/bhtable.h"
#include "sm/io.h"
#include "sm/smardef.h"
#include "smar.h"
#include "t-init.h"
#define SMAR_LOG_DEFINES 1
#include "log.h"

/*
**  Test program for (a subset of) access checks.
**  This program is directly linked against the smar functions that
**  perform the tests, it does not communicate with an smar daemon.
**  This is done to allow for direct testing of one component instead
**  of the significantly more complicated part of communicating with
**  an smar daemon (which is done by other test programs).
*/

static int Verbose = 0;
int Loglevel = 9;

#define TRS_FL_NORECERR	0x0001 /* ignore recursion error */

/*
**   T_ACC_0_INIT -- Initialize smar_ctx
**	See smar_init1(), this is the part of it that is necessary for
**	access map lookups.
**
**	Parameters:
**		smar_ctx -- SMAR context
**
**	Returns:
**		usual sm_error code
*/

static sm_ret_T
t_acc_0_init(smar_ctx_P smar_ctx)
{
	return t_smar_0_init(smar_ctx,
		TSMARI_FL_MT|TSMARI_FL_ALIAS|TSMARI_FL_ACC|TSMARI_FL_STR);
}

/*
**   T_ACC_0_FREE -- Free data in smar_ctx
**
**	Parameters:
**		smar_ctx -- SMAR context
**
**	Returns:
**		usual sm_error code
*/

static void
t_acc_0_free(smar_ctx_P smar_ctx)
{
	if (smar_ctx->smar_mt_map != NULL)
	{
		(void) sm_map_close(smar_ctx->smar_mt_map, 0);
		smar_ctx->smar_mt_map = NULL;
	}
	if (smar_ctx->smar_aliases != NULL)
	{
		(void) sm_map_close(smar_ctx->smar_aliases, 0);
		smar_ctx->smar_aliases = NULL;
	}
	if (smar_ctx->smar_maps != NULL)
	{
		(void) sm_maps_term(smar_ctx->smar_maps);
		smar_ctx->smar_maps = NULL;
	}
}

/*
**  T_ACC_0 -- Perform access check
**
**	Parameters:
**		addr -- (printable) address to expand.
**
**	Returns:
**		none.
*/

static void
t_acc_0(char *addr, uint32_t ltype, uint lflags, sm_str_P srch, ipv4_T ipv4)
{
	sm_ret_T ret;
	sm_str_P str;
	smar_addr_P smar_addr;
	smar_ctx_T smar_ctx;

	ret = t_acc_0_init(&smar_ctx);
	SM_TEST(ret == SM_SUCCESS);
	if (ret != SM_SUCCESS)
		return;
	smar_ctx.smar_cnf.smar_cnf_alias_fl = SMARCNF_FL_MAP_LP|
						SMARCNF_FL_MAP_LD;
	smar_ctx.smar_alias_lfl = SMMAP_LFL_ALIAS;
	ret = smar_init_map_lfl(&smar_ctx, smar_ctx.smar_cnf.smar_cnf_alias_fl,
				&smar_ctx.smar_alias_lfl);
	SM_TEST(ret == SM_SUCCESS);
	if (ret != SM_SUCCESS)
		return;

	ret = smar_addr_new(NULL, &smar_addr);
	SM_TEST(ret == SM_SUCCESS);
	if (ret != SM_SUCCESS)
		return;

	str = sm_str_new(NULL, MAXADDRLEN, MAXADDRLEN + 2);
	SM_TEST(str != NULL);
	if (str == NULL)
		return;
	ret = sm_str_scopy(str, addr);
	SM_TEST(ret == SM_SUCCESS);

	smar_addr->ara_ltype = ltype;
	smar_addr->ara_lflags = lflags;
	smar_addr->ara_pa = str;
	smar_addr->ara_pa2 = srch;
	smar_addr->ara_ipv4 = ipv4;
	SMARA_SET_FLAG(smar_addr, SMARA_FL_RCVDIPV4);

	ret = smar_access_chk(&smar_ctx, smar_addr);

	if (ret == SM_SUCCESS)
	{
		sm_io_fprintf(smioout, "ara_status=%r\n",
			smar_addr->ara_status);
		sm_io_flush(smioout);
	}
	else if (Verbose > 0)
		sm_io_fprintf(smioerr, "smar_rcpt_expand=%#X\n", ret);

	SM_TEST(ret == SM_SUCCESS);
	t_acc_0_free(&smar_ctx);
}

/*
**  USAGE -- usage message
**
**	Parameters:
**		prg -- program name
**
**	Returns:
**		none
*/

static void
usage(const char *prg)
{
	sm_io_fprintf(smioerr, "usage: %s [options] addresses...\n"
		"-D         implicitly match +detail for protected addresses\n"
#if SMAR_DEBUG
		"-d level   set debug level\n"
#endif
		"-f flags   set lookup flags\n"
		"-i address set lookup type SMARA_LT_RCPT_PROT\n"
		"-l type    set lookup type\n"
		"-m         use map matching for protected addresses\n"
		"           must be used together with -p\n"
		"-p str     try protected address str\n"
		"-S addr    specify address (e.g., to find in list)\n"
		"-V         increase verbosity\n"
		, prg
		);
	return;
}

int
main(int argc, char *argv[])
{
	int c, i;
	uint32_t ltype;
	uint lflags;
	ipv4_T ipv4;
	sm_str_P srch;

	lflags = 0;
	ltype = SMARA_LT_RCPT_ACC;
	srch = NULL;
	ipv4 = 0;
	while ((c = getopt(argc, argv, "Dd:f:i:l:mp:S:Vv:")) != -1)
	{
		switch (c)
		{
		  case 'D':
			lflags |= SMARA_LFL_PROTIMPLDET;
			break;
		  case 'd':
#if SMAR_DEBUG
			smar_debug = (uint) strtoul(optarg, NULL, 0);
#endif
			break;
		  case 'f':
			lflags = (uint) strtoul(optarg, NULL, 0);
			break;
		  case 'i':
			ltype = SMARA_LT_RCPT_PROT;
			lflags |= SMARA_LFL_2821;
			i = sm_inet_a2ipv4(optarg, NULL, &ipv4);
			break;
		  case 'l':
			ltype = (uint) strtoul(optarg, NULL, 0);
			break;
		  case 'm':
			lflags |= SMARA_LFL_PROTMAP;
			break;
		  case 'p':
			ltype = SMARA_LT_RCPT_PROT;
			lflags |= SMARA_LFL_2821;
			srch = sm_str_scpy(NULL, optarg, 256);
			break;
		  case 'S':
			srch = sm_str_scpy(NULL, optarg, 256);
			break;
		  case 'V':
			++Verbose;
			break;
		  case 'v':
			Loglevel = (uint) strtoul(optarg, NULL, 0);
			break;
		  default:
			usage(argv[0]);
			return 1;
		}
	}

	sm_test_begin(argc, argv, "test rcpts 0");
	argc -= optind;
	argv += optind;
	if (argc > 0)
	{
		for (i = 0; i < argc; i++)
			t_acc_0(argv[i], ltype, lflags, srch, ipv4);
	}
	else
		t_acc_0("<a@b.c>", ltype, lflags, srch, ipv4);
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1