/* * Copyright (c) 2004, 2005 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. */ #define SM_SSCNFDEF 1 #include "sm/generic.h" SM_RCSID("@(#)$Id: ssconf.c,v 1.35 2007/06/02 04:25:01 ca Exp $") #include "sm/error.h" #include "sm/assert.h" #include "sm/sysexits.h" #include "sm/string.h" #include "sm/io.h" #include "sm/sm-conf.h" #include "sm/sm-conf-prt.h" #include "sm/qmgrcomm.h" #include "smtps-str.h" #define SM_LOG_IDENT "smtps" #define SM_CONF_LOG_DEF 1 #define SM_CONF_TIME_DEF 1 #define SM_CONF_BYTE_DEF 1 #define SM_CONF_KBYTE_DEF 1 #define SM_SOCKCNFDEF 1 #include "sm/sockcnf.h" #include "sm/sockcnfdef.h" #include "smtps.h" #include "log.h" #include "sm/sscnf.h" #include "sm/sscnfdef.h" /* ** SS_CHK_CNF -- Check configuration for consistency ** ** Parameters: ** ss_ctx -- SMTP Server context ** ** Returns: ** usual return code */ sm_ret_T ss_chk_cnf(ss_ctx_P ss_ctx) { sm_ret_T ret; ss_cnf_T ssc_cnf; ssc_cnf = ss_ctx->ssc_cnf; ret = SM_SUCCESS; if (ssc_cnf.ss_cnf_r_ta_lim < ssc_cnf.ss_cnf_r_tot_lim) { ssc_cnf.ss_cnf_r_ta_lim = ssc_cnf.ss_cnf_r_tot_lim; /* complain?? */ } if (SSC_IS_CFLAG(ss_ctx, SSC_CFL_PROTMAP) && !SSC_IS_CFLAG(ss_ctx, SSC_CFL_PROTBYMAIL|SSC_CFL_PROTBYCLTADDR)) { sm_log_write(ss_ctx->ssc_lctx, SS_LCAT_CONFIG, SS_LMOD_CONFIG, SM_LOG_ERROR, 6, "sev=ERROR, func=ss_chk_cnf, option=%s, requires=%s|%s" , SS_PR_CNF, SS_PR_A_SENDER, SS_PR_A_CLTADDR); ret = sm_err_perm(EINVAL); } if (SSC_IS_CFLAG(ss_ctx, SSC_CFL_SE_CONF) && !SSC_IS_CFLAG(ss_ctx, SSC_CFL_ACCESS_DB)) { sm_log_write(ss_ctx->ssc_lctx, SS_LCAT_CONFIG, SS_LMOD_CONFIG, SM_LOG_WARN, 6, "sev=WARN, func=ss_chk_cnf, option=%s, requires=%s, status=turned_on_implicitly" , SS_LKP_SE_CONF, SS_CNFN_ACCESS); SSC_SET_CFLAG(ss_ctx, SSC_CFL_ACCESS_DB); } if (SSC_IS_CFLAG(ss_ctx, SSC_CFL_PROTIMPLDET) && !SSC_IS_CFLAG(ss_ctx, SSC_CFL_PROTMAP)) { sm_log_write(ss_ctx->ssc_lctx, SS_LCAT_CONFIG, SS_LMOD_CONFIG, SM_LOG_WARN, 6, "sev=WARN, func=ss_chk_cnf, option=%s, flag=%s, requires=%s, status=turned_on_implicitly" , SS_PR_CNF, SS_IMPLDET, SS_PR_USE_LOOKUP); SSC_SET_CFLAG(ss_ctx, SSC_CFL_PROTMAP); } return ret; } /* ** SS_READ_CNF -- Read configuration file ** ** Parameters: ** ss_ctx -- SMTP server context ** fn -- filename of configuration file ** psmc -- (pointer to) configuration context (output) ** ** Returns: ** 0 on success, everything else is an error */ sm_ret_T ss_read_cnf(ss_ctx_P ss_ctx, const char *fn, sm_conf_T **psmc) { int err, i; sm_conf_T *smc; FILE *fp; sm_conf_iterator_T ss_cnf_iter; char const *ss_cnf_name; size_t ss_cnf_name_n; char thissmtps[MAXSECTIONNAME]; extern int Sk_count; extern ss_socket_ctx_T ss_sck_ctx[]; fp = NULL; smc = sm_conf_new(fn); if (NULL == smc) { err = errno; sm_io_fprintf(smioerr, "%s: sm_conf_new=NULL, errno=%d\n", fn, err); return sm_error_temp(SM_EM_Q_CONF, ENOMEM); } err = sm_conf_read_FILE(smc, fn, fp); if (err != 0) { sm_prt_conferr(fn, smc, err, smioerr); goto error; } err = sm_conf_scan(smc, ss_global_defs, SM_CONF_FLAG_ALLOW_ANY, &ss_ctx->ssc_cnf); if (err != 0) { sm_prt_conferr(fn, smc, err, smioerr); goto error; } ss_cnf_iter = NULL; if (ss_ctx->ssc_cnf.ss_cnf_section != NULL) sm_snprintf(thissmtps, sizeof(thissmtps), "smtps{%s}", ss_ctx->ssc_cnf.ss_cnf_section); else strlcpy(thissmtps, "smtps", sizeof(thissmtps)); err = sm_conf_scan_next(smc, thissmtps, ss_defs, 0, &ss_cnf_name, &ss_cnf_name_n, &ss_ctx->ssc_cnf, &ss_cnf_iter); if (err != 0 && (ss_ctx->ssc_cnf.ss_cnf_section != NULL || err != SM_CONF_ERR_NOT_FOUND)) sm_prt_conferr(fn, smc, err, smioerr); else err = 0; /* ** HACK: transfer configuration data to "global" data ** as simple strings which will be parsed later on. ** This will go away as soon as the configuration ** definition evolves... */ while (Sk_count < SS_MAX_BIND_ADDRS && ss_ctx->ssc_cnf.ss_cnf_sck_addr[Sk_count] != NULL) { ss_sck_ctx[Sk_count].sssc_addr = ss_ctx->ssc_cnf.ss_cnf_sck_addr[Sk_count]; ++Sk_count; ++ss_ctx->ssc_cnf.ss_cnf_sk_count; } if (ss_ctx->ssc_cnf.ss_cnf_relay_to != NULL) err = ss_relay_to(ss_ctx, ss_ctx->ssc_cnf.ss_cnf_relay_to); if (err == 0 && ss_ctx->ssc_cnf.ss_cnf_relay_from != NULL) err = ss_relay_from(ss_ctx, ss_ctx->ssc_cnf.ss_cnf_relay_from); if (err != SM_SUCCESS) goto error; if (ss_ctx->ssc_cnf.ss_cnf_hostname != NULL) { size_t l; l = strlen(ss_ctx->ssc_cnf.ss_cnf_hostname) + 1; ss_ctx->ssc_hostname = sm_str_scpyn0(NULL, ss_ctx->ssc_cnf.ss_cnf_hostname, l, l); if (NULL == ss_ctx->ssc_hostname) { err = sm_error_temp(SM_EM_Q_CONF, ENOMEM); goto error; } } #if MTA_USE_PMILTER /* is a policy_milter socket specified? if yes: set flag */ if (ss_ctx->ssc_cnf.ss_cnf_miltsockspec.sckspc_type != 0) SM_SET_FLAG(ss_ctx->ssc_cnf.ss_cnf_cflags, SSC_CFL_PMILTER); #endif #if 0 err = sm_conf_scan_next(smc, "ss.log", ss_defs, 0, &conf_name, &conf_name_n, &s, &conf_iter); #endif i = ss_ctx->ssc_cnf.ss_cnf_log.sm_logspc_facility; /* ** HACK! it should check whether log is in config file ** however it's not clear how to do that... ** this only works because facility 0 is KERN. */ if (i != 0) { err = sm_log_opensyslog( ss_ctx->ssc_cnf.ss_cnf_log.sm_logspc_ident, ss_ctx->ssc_cnf.ss_cnf_log.sm_logspc_opt, i); if (sm_is_err(err)) goto error; err = sm_log_setfp_fd(ss_ctx->ssc_lctx, NULL, INVALID_FD); if (sm_is_err(err)) goto error; } (void) ss_chk_cnf(ss_ctx); if (psmc != NULL) *psmc = smc; return err; error: if (smc != NULL) { sm_conf_destroy(smc); smc = NULL; } return err; } #if STANDALONE static int process(char const *name, FILE *fp) { sm_conf_T *stream; int err; ss_cnf_T s; sm_conf_iterator_T qm_cnf_iter; char const *qm_cnf_name; size_t qm_cnf_name_n; if (((stream = sm_conf_new(name ? name : "*stdin*"))) == NULL) { fprintf(stderr, "error -- sm_conf_new() returns NULL!\n"); return 1; } if ((err = sm_conf_read_FILE(stream, name, fp)) != 0) { char buf[200]; char const *e = NULL; fprintf(stderr, "%s: %s\n", name ? name : "*stdin*", sm_conf_strerror(err, buf, sizeof buf)); while ((e = sm_conf_syntax_error(stream, e)) != NULL) fprintf(stderr, "%s\n", e); sm_conf_destroy(stream); return 2; } qm_cnf_iter = NULL; while ((err = sm_conf_scan_next(stream, "smtps", mcp_defs, 0, &qm_cnf_name, &qm_cnf_name_n, &s, &qm_cnf_iter)) == 0) { print_structure(&s, qm_cnf_name, qm_cnf_name_n); } if (err != 0 && err != SM_CONF_ERR_NOT_FOUND) { char buf[200]; char const *e = NULL; fprintf(stderr, "(while scanning) %s: %s\n", name ? name : "*stdin*", sm_conf_strerror(err, buf, sizeof buf)); while ((e = sm_conf_syntax_error(stream, e)) != NULL) fprintf(stderr, "%s\n", e); sm_conf_destroy(stream); return 3; } sm_conf_destroy(stream); return 0; } int main(int ac, char **av) { int ret; int ai; ret = 0; /* make compiler happy */ if (1 == ac) ret = process("*stdin*", stdin); else { for (ai = 1; ai < ac; ai++) { ret = process(av[ai], NULL); if (ret != 0) break; } } return ret; } #endif /* STANDALONE */