/* * Copyright (c) 2007 Claus Assmann * * By using this file, you agree to the terms and conditions set * forth in the license/LICENSE.3C file which can be found at the * top level of this source code distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: pmilter_setreplies.c,v 1.4 2007/02/13 03:58:18 ca Exp $") #include "sm/error.h" #include "sm/assert.h" #include "sm/ctype.h" #include "pmilter.h" #include "sm/pmfdef.h" #include "sm/pmfapi.h" #if MTA_USE_PMILTER && MTA_USE_RSAD /* ** SM_PM_CLRREPLIES -- Clear replies in session context ** ** Parameters: ** pmse_ctx -- pmilter/SMTP server session context ** ** Returns: ** usual sm_error code */ sm_ret_T pm_clrreplies(pmse_ctx_P pmse_ctx) { sm_ret_T ret; SM_IS_PMSE_CTX(pmse_ctx); ret = SM_SUCCESS; if (pmse_ctx->pmse_nreplies > 0 && pmse_ctx->pmse_rcodes != NULL) SM_FREE(pmse_ctx->pmse_rcodes); if (pmse_ctx->pmse_nreplies > 0 && pmse_ctx->pmse_replies != NULL) { uint u; sm_str_P reply; for (u = 0; u < pmse_ctx->pmse_nreplies; u++) { reply = pmse_ctx->pmse_replies[u]; SM_STR_FREE(reply); } SM_FREE(pmse_ctx->pmse_replies); } pmse_ctx->pmse_nreplies = 0; return ret; } /* ** SM_PMFI_SETREPLIES -- Set replies for several commands ** ** Parameters: ** pmse_ctx -- pmilter/SMTP server session context ** nreplies -- number of entries in replies array ** rcodes -- array of reply codes ** rtexts -- array of reply texts including error codes (can be NULL) ** ** Returns: ** usual sm_error code */ sm_ret_T sm_pmfi_setreplies(pmse_ctx_P pmse_ctx, uint nreplies, int *rcodes, const char **rtexts) { sm_ret_T ret; uint u; int i; const char *rtext; SM_IS_PMSE_CTX(pmse_ctx); ret = SM_SUCCESS; if (NULL == rcodes || 0 == nreplies) return sm_err_perm(EINVAL); (void) pm_clrreplies(pmse_ctx); /* check codes */ for (u = 0; u < nreplies; u++) { i = rcodes[u] / 100; if (i < 2 || i > 5) return sm_err_perm(EINVAL); } pmse_ctx->pmse_nreplies = nreplies; u = nreplies * sizeof(*pmse_ctx->pmse_rcodes); if (u <= nreplies || u < sizeof(*pmse_ctx->pmse_rcodes)) return sm_err_perm(SM_E_OVFLW_SC); pmse_ctx->pmse_rcodes = (int *) sm_zalloc(u); if (NULL == pmse_ctx->pmse_rcodes) return sm_err_temp(ENOMEM); /* copy codes */ for (u = 0; u < nreplies; u++) pmse_ctx->pmse_rcodes[u] = rcodes[u]; if (NULL == rtexts) return SM_SUCCESS; /* check rtexts */ ret = sm_err_perm(EINVAL); for (u = 0; u < nreplies; u++) { size_t len; char c; rtext = rtexts[u]; if (NULL == rtext) goto error; len = strlen(rtext); if (len < 5) goto error; c = rtext[0]; if (c != '2' && c != '3' && c != '4' && c != '5') goto error; if (!ISDIGIT(rtext[1]) || !ISDIGIT(rtext[2])) goto error; if (rtext[len - 2] != '\r' || rtext[len - 1] != '\n') goto error; } pmse_ctx->pmse_nreplies = nreplies; u = nreplies * sizeof(*pmse_ctx->pmse_replies); if (u <= nreplies || u < sizeof(*pmse_ctx->pmse_replies)) { ret = sm_err_perm(SM_E_OVFLW_SC); goto error; } pmse_ctx->pmse_replies = (sm_str_P *) sm_zalloc(u); if (NULL == pmse_ctx->pmse_replies) goto enomem; /* next: copy */ for (u = 0; u < nreplies; u++) { rtext = rtexts[u]; pmse_ctx->pmse_replies[u] = sm_str_scpy(NULL, rtext, strlen(rtext)); if (NULL == pmse_ctx->pmse_replies[u]) goto enomem; } return SM_SUCCESS; enomem: ret = sm_err_temp(ENOMEM); error: (void) pm_clrreplies(pmse_ctx); return ret; } #endif /* MTA_USE_PMILTER && MTA_USE_RSAD */