int msgmod_change_header(void *ctx, int argc, var_t *args[]) { char *headerf; char *headerv; long index = 1; if (argc < 2 || argc > 3) { log_error("msgmod_change_header: bad argument count"); return -1; } headerf = args[0]->v_data; headerv = args[1]->v_data; if (argc == 3) { index = atol(args[2]->v_data); } if (smfi_chgheader(ctx, headerf, index, headerv) != MI_SUCCESS) { log_error("msgmod_change_header: smfi_chgheader failed"); return -1; } log_debug("msgmod_change_header: %s: %s (%d)", headerf, headerv, index); return 0; }
static void add_x_header(SMFICTX *ctx, char *st, unsigned int scanned, unsigned int status) { if(addxvirus == 1) { /* Replace/Yes */ while(scanned) if(smfi_chgheader(ctx, (char *)"X-Virus-Scanned", scanned--, NULL) != MI_SUCCESS) logg("^Failed to remove existing X-Virus-Scanned header\n"); while(status) if(smfi_chgheader(ctx, (char *)"X-Virus-Status", status--, NULL) != MI_SUCCESS) logg("^Failed to remove existing X-Virus-Status header\n"); if(smfi_addheader(ctx, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) logg("^Failed to add X-Virus-Scanned header\n"); if(smfi_addheader(ctx, (char *)"X-Virus-Status", st) != MI_SUCCESS) logg("^Failed to add X-Virus-Status header\n"); } else { /* Add */ if(smfi_insheader(ctx, 1, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) logg("^Failed to insert X-Virus-Scanned header\n"); if(smfi_insheader(ctx, 1, (char *)"X-Virus-Status", st) != MI_SUCCESS) logg("^Failed to insert X-Virus-Status header\n"); } }
static sfsistat test_eom(SMFICTX *ctx) { printf("test_eom\n"); #ifdef SMFIR_REPLBODY if (body_file) { char buf[BUFSIZ + 2]; FILE *fp; size_t len; int count; if ((fp = fopen(body_file, "r")) == 0) { perror(body_file); } else { printf("replace body with content of %s\n", body_file); for (count = 0; fgets(buf, BUFSIZ, fp) != 0; count++) { len = strcspn(buf, "\n"); buf[len + 0] = '\r'; buf[len + 1] = '\n'; if (smfi_replacebody(ctx, buf, len + 2) == MI_FAILURE) { fprintf(stderr, "body replace failure\n"); exit(1); } if (verbose) printf("%.*s\n", (int) len, buf); } if (count == 0) perror("fgets"); (void) fclose(fp); } } #endif #ifdef SMFIR_CHGFROM if (chg_from != 0 && smfi_chgfrom(ctx, chg_from, "whatever") == MI_FAILURE) fprintf(stderr, "smfi_chgfrom failed\n"); #endif #ifdef SMFIR_INSHEADER if (ins_hdr && smfi_insheader(ctx, ins_idx, ins_hdr, ins_val) == MI_FAILURE) fprintf(stderr, "smfi_insheader failed\n"); #endif #ifdef SMFIR_CHGHEADER if (chg_hdr && smfi_chgheader(ctx, chg_hdr, chg_idx, chg_val) == MI_FAILURE) fprintf(stderr, "smfi_chgheader failed\n"); #endif { int count; for (count = 0; count < rcpt_count; count++) if (smfi_addrcpt(ctx, rcpt_addr[count]) == MI_FAILURE) fprintf(stderr, "smfi_addrcpt `%s' failed\n", rcpt_addr[count]); } return (test_reply(ctx, test_eom_reply)); }
/*}}}*/ } priv_t; static char * xfree (char *s) /*{{{*/ { if (s) free (s); return NULL; }/*}}}*/ static bool_t xcopy (char **buf, const char *str) /*{{{*/ { if (*buf) free (*buf); *buf = str ? strdup (str) : NULL; return (! str) || *buf ? true : false; }/*}}}*/ static void priv_clear (priv_t *p) /*{{{*/ { if (p) { p -> x_agn = 0; p -> from = xfree (p -> from); p -> receiver = charc_free_all (p -> receiver); p -> prev = NULL; p -> info = xfree (p -> info); } }/*}}}*/ static priv_t * priv_free (priv_t *p) /*{{{*/ { if (p) { priv_clear (p); if (p -> lg) log_free (p -> lg); if (p -> cfg) cfg_free (p -> cfg); free (p); } return NULL; }/*}}}*/ static priv_t * priv_alloc (void) /*{{{*/ { priv_t *p; if (p = (priv_t *) malloc (sizeof (priv_t))) if (p -> cfg = cfg_alloc (cfgfile)) { p -> is_local = false; p -> x_agn = 0; p -> from = NULL; p -> receiver = NULL; p -> prev = NULL; p -> info = NULL; if (! (p -> lg = log_alloc (NULL, program, loglevel))) p = priv_free (p); } else { free (p); p = NULL; } return p; }/*}}}*/ static bool_t priv_setfrom (priv_t *p, const char *from) /*{{{*/ { return xcopy (& p -> from, from); }/*}}}*/ static bool_t priv_setto (priv_t *p, const char *to) /*{{{*/ { charc_t *r; if (r = charc_alloc (to)) { if (p -> prev) p -> prev -> next = r; else p -> receiver = r; p -> prev = r; } return r ? true : false; }/*}}}*/ static bool_t priv_addinfo (priv_t *p, const char *info) /*{{{*/ { char *temp; if ((! p -> info) || (! p -> info[0])) return xcopy (& p -> info, info); if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) { sprintf (temp, "%s,%s", p -> info, info); free (p -> info); p -> info = temp; return true; } return false; }/*}}}*/ static bool_t priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/ { bool_t rc; char *scratch, *ptr; if (scratch = malloc (strlen (var) + strlen (val) + 2)) { for (ptr = scratch; *var; *ptr++ = *var++) ; *ptr++ = '='; for (;*val; ++val) *ptr++ = *val == ',' ? '_' : *val; *ptr = '\0'; rc = priv_addinfo (p, scratch); free (scratch); } else rc = false; return rc; }/*}}}*/ static sfsistat handle_connect (SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) /*{{{*/ { priv_t *p; if (! (p = priv_alloc ())) return SMFIS_TEMPFAIL; if (hostaddr -> sa_family == AF_INET) { struct sockaddr_in *iaddr = (struct sockaddr_in *) hostaddr; if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK) p -> is_local = true; } # ifdef AF_INET6 else if (hostaddr -> sa_family == AF_INET6) { struct sockaddr_in6 *i6addr = (struct sockaddr_in6 *) hostaddr; static struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT; if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0) p -> is_local = true; } # endif /* AF_INET6 */ smfi_setpriv (ctx, p); return SMFIS_CONTINUE; }/*}}}*/ static sfsistat handle_from (SMFICTX *ctx, char **argv) /*{{{*/ { priv_t *p = (priv_t *) smfi_getpriv (ctx); if (! p) return SMFIS_TEMPFAIL; priv_clear (p); if (! priv_setfrom (p, argv[0])) return SMFIS_TEMPFAIL; priv_addinfopair (p, "from", argv[0]); return SMFIS_CONTINUE; }/*}}}*/ static sfsistat handle_to (SMFICTX *ctx, char **argv) /*{{{*/ { priv_t *p = (priv_t *) smfi_getpriv (ctx); char *chk, *opt; bool_t reject, tempfail; if (! p) return SMFIS_TEMPFAIL; if (p -> is_local) return SMFIS_CONTINUE; if (! (chk = cfg_valid_address (p -> cfg, argv[0]))) { log_out (p -> lg, LV_ERROR, "Unable to setup initial data for `%s'", argv[0]); return SMFIS_TEMPFAIL; } if (opt = strchr (chk, ':')) *opt++ = '\0'; reject = false; tempfail = false; if (! strcmp (chk, ID_REJECT)) reject = true; else if (! strcmp (chk, ID_TEMPFAIL)) tempfail = true; else if ((! strcmp (chk, ID_ACCEPT)) && opt) priv_addinfo (p, opt); priv_addinfopair (p, "to", argv[0]); free (chk); if (reject) { log_out (p -> lg, LV_INFO, "Receiver `%s' is rejected", argv[0]); smfi_setreply (ctx, (char *) "550", (char *) "5.1.1", (char *) "No such user"); return SMFIS_REJECT; } if (tempfail) { log_out (p -> lg, LV_INFO, "Receiver `%s' is temp. disbaled", argv[0]); smfi_setreply (ctx, (char *) "400", (char *) "4.0.0", (char *) "Please try again later"); return SMFIS_TEMPFAIL; } if (! priv_setto (p, argv[0])) return SMFIS_TEMPFAIL; return SMFIS_CONTINUE; }/*}}}*/ static sfsistat handle_header (SMFICTX *ctx, char *field, char *value) /*{{{*/ { priv_t *p = (priv_t *) smfi_getpriv (ctx); if (! p) return SMFIS_TEMPFAIL; if (p -> is_local) return SMFIS_CONTINUE; if (! strcasecmp (field, X_LOOP)) { log_out (p -> lg, LV_WARNING, "Mail from `%s' has already loop marker set, rejected", p -> from); smfi_setreply (ctx, (char *) "500", (char *) "5.4.6", (char *) "Loop detected"); return SMFIS_REJECT; } if (! strcasecmp (field, X_AGN)) p -> x_agn++; return SMFIS_CONTINUE; }/*}}}*/ static sfsistat handle_eom (SMFICTX *ctx) /*{{{*/ { priv_t *p = (priv_t *) smfi_getpriv (ctx); int n; if (! p) return SMFIS_TEMPFAIL; for (n = 0; n < p -> x_agn; ++n) smfi_chgheader (ctx, (char *) X_AGN, 0, NULL); if (! p -> is_local) { if (p -> info) smfi_addheader (ctx, (char *) X_AGN, p -> info); smfi_addheader (ctx, (char *) X_LOOP, (char *) LOOP_SET); } return SMFIS_CONTINUE; }/*}}}*/
int msgmod_delete_header(void *ctx, int argc, var_t *args[]) { char *headerf; if (argc != 1) { log_error("msgmod_delete_header: bad argument count"); return -1; } headerf = args[0]->v_data; if (smfi_chgheader(ctx, headerf, 1, NULL) != MI_SUCCESS) { log_error("msgmod_delete_header: smfi_chgheader failed"); return -1; } log_debug("msgmod_delete_header: %s (1)", headerf); return 0; }