/* * 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: pmilter_rcptmod.c,v 1.5 2006/10/05 04:27:38 ca Exp $") #include "sm/error.h" #include "sm/assert.h" #include "pmilter.h" #include "sm/pmfdef.h" #include "sm/pmfapi.h" #include "sm/pmilter.h" #if MTA_USE_PMILTER /* ** PM_RCPTS_NEW -- add a new recipient to the recipient list ** ** Parameters: ** pmse_ctx -- SMTP server transaction context ** rcpt_pa -- recipient (printable address, RFC 2821) ** len -- len of rcpt_pa ** ppm_rcpt -- (pointer to) new recipient (output) ** ** Returns: ** usual return code */ static sm_ret_T pm_rcpt_add(pmse_ctx_P pmse_ctx, const char *rcpt_pa, uint len, rcpt_idx_T rcpt_idx, pm_rcpt_P *ppm_rcpt) { pm_rcpt_P pm_rcpt; SM_REQUIRE(ppm_rcpt != NULL); pm_rcpt = (pm_rcpt_P) sm_zalloc(sizeof(*pm_rcpt)); if (NULL == pm_rcpt) return sm_err_temp(ENOMEM); pm_rcpt->pmr_pa = sm_str_scpyn0(NULL, rcpt_pa, len + 1, len + 2); if (NULL == pm_rcpt->pmr_pa) goto error; PM_RCPTS_INSERT_TAIL(&pmse_ctx->pmse_rcpts_hd, pm_rcpt); pm_rcpt->pmr_idx = rcpt_idx; *ppm_rcpt = pm_rcpt; return SM_SUCCESS; error: SM_STR_FREE(pm_rcpt->pmr_pa); SM_FREE(pm_rcpt); *ppm_rcpt = NULL; return sm_err_temp(ENOMEM); } /* ** PM_RCPTS_FREE -- free an entire recipient list ** ** Parameters: ** pmse_ctx -- SMTP server transaction context ** ** Returns: ** usual return code */ sm_ret_T pm_rcpts_free(pmse_ctx_P pmse_ctx) { pm_rcpt_P pm_rcpt; while (!PM_RCPTS_EMPTY(&pmse_ctx->pmse_rcpts_hd)) { pm_rcpt = PM_RCPTS_FIRST(&pmse_ctx->pmse_rcpts_hd); PM_RCPTS_REMOVE_HEAD(&pmse_ctx->pmse_rcpts_hd); SM_STR_FREE(pm_rcpt->pmr_pa); SM_FREE(pm_rcpt); } PM_RCPTS_INIT(&pmse_ctx->pmse_rcpts_hd); return SM_SUCCESS; } /* ** PM_RCPT_MOD -- Add or delete recipient ** ** Parameters: ** pmse_ctx -- pmilter/SMTP server session context ** rcpt_pa -- recipient (rfc 2821 format) ** rcpt_idx -- recipient index ** type -- add/delete ** ** Returns: ** usual sm_error code */ static sm_ret_T pm_rcpt_mod(pmse_ctx_P pmse_ctx, const char *rcpt_pa, rcpt_idx_T rcpt_idx, uint type) { sm_ret_T ret; pm_rcpt_P pm_rcpt; size_t len; SM_IS_PMSE_CTX(pmse_ctx); if (NULL == rcpt_pa) return sm_error_perm(SM_EM_PMILTER, EINVAL); if (!SM_IS_FLAG(pmse_ctx->pmse_pmss_ctx->pmss_pmcap, SM_SCAP_PM_RCPTMOD)) return sm_error_perm(SM_EM_PMILTER, SM_E_PR_ERR); if (pmse_ctx->pmse_state != PMSE_ST_DOT) return sm_error_perm(SM_EM_PMILTER, SM_E_PR_ERR); pm_rcpt = NULL; len = strlen((const char *) rcpt_pa); if (len < 5 || len > MAXADDRLEN) return sm_error_perm(SM_EM_PMILTER, EINVAL); if (rcpt_pa[0] != '<' || rcpt_pa[len - 1] != '>') return sm_error_perm(SM_EM_PMILTER, EINVAL); /* do a full syntax check here?? */ ret = pm_rcpt_add(pmse_ctx, rcpt_pa, len, rcpt_idx, &pm_rcpt); if (sm_is_err(ret)) return ret; pm_rcpt->pmr_type = type; return SM_SUCCESS; } /* ** SM_PMFI_RCPT_ADD -- Add recipient ** ** Parameters: ** pmse_ctx -- pmilter/SMTP server session context ** rcpt_pa -- recipient (rfc 2821 format) ** argv -- list of SMTP parameter for RCPT; NULL terminated list. ** (currently ignored) ** ** Returns: ** usual sm_error code */ sm_ret_T sm_pmfi_rcpt_add(pmse_ctx_P pmse_ctx, const char *rcpt_pa, char **argv) { return pm_rcpt_mod(pmse_ctx, rcpt_pa, 0, PM_RCPT_ADD); } /* ** SM_PMFI_RCPT_DEL -- Delete recipient ** ** Parameters: ** pmse_ctx -- pmilter/SMTP server session context ** rcpt_pa -- recipient (rfc 2821 format) ** rcpt_idx -- recipient index ** ** Returns: ** usual sm_error code */ sm_ret_T sm_pmfi_rcpt_del(pmse_ctx_P pmse_ctx, const char *rcpt_pa, rcpt_idx_T rcpt_idx) { return pm_rcpt_mod(pmse_ctx, rcpt_pa, rcpt_idx, PM_RCPT_DEL); } #endif /* MTA_USE_PMILTER */