static void scache_single_save_dest(SCACHE *scache, int dest_ttl, const char *dest_label, const char *dest_prop, const char *endp_label) { SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache; const char *myname = "scache_single_save_dest"; int refresh; if (dest_ttl <= 0) msg_panic("%s: bad dest_ttl: %d", myname, dest_ttl); /* * Optimize: reset timer only, if nothing has changed. */ refresh = (SCACHE_SINGLE_DEST_BUSY(sp) && strcmp(STR(sp->dest.dest_label), dest_label) == 0 && strcmp(STR(sp->dest.dest_prop), dest_prop) == 0 && strcmp(STR(sp->dest.endp_label), endp_label) == 0); if (refresh == 0) { vstring_strcpy(sp->dest.dest_label, dest_label); vstring_strcpy(sp->dest.dest_prop, dest_prop); vstring_strcpy(sp->dest.endp_label, endp_label); } event_request_timer(scache_single_expire_dest, (char *) sp, dest_ttl); if (msg_verbose) msg_info("%s: %s -> %s%s", myname, dest_label, endp_label, refresh ? " (refreshed)" : ""); }
static void update_entry(const char *new_channel, const char *new_nexthop, const char *rcpt_domain, VSTRING *channel, VSTRING *nexthop) { /* * :[nexthop] means don't change the channel, and don't change the * nexthop unless a non-default nexthop is specified. Thus, a right-hand * side of ":" is the transport table equivalent of a NOOP. */ if (*new_channel == 0) { /* :[nexthop] */ if (*new_nexthop != 0) vstring_strcpy(nexthop, new_nexthop); } /* * transport[:[nexthop]] means change the channel, and reset the nexthop * to the default unless a non-default nexthop is specified. */ else { vstring_strcpy(channel, new_channel); if (*new_nexthop != 0) vstring_strcpy(nexthop, new_nexthop); else if (strcmp(STR(channel), MAIL_SERVICE_ERROR) != 0 && strcmp(STR(channel), MAIL_SERVICE_RETRY) != 0) vstring_strcpy(nexthop, rcpt_domain); else vstring_strcpy(nexthop, "Address is undeliverable"); } }
static void xsasl_dovecot_parse_reply_args(XSASL_DOVECOT_SERVER *server, char *line, VSTRING *reply, int success) { char *next; if (server->username) { myfree(server->username); server->username = 0; } /* * Note: TAB is part of the Dovecot protocol and must not appear in * legitimate Dovecot usernames, otherwise the protocol would break. */ for (; line != NULL; line = next) { next = split_at(line, '\t'); if (strncmp(line, "user="******"reason=", 7) == 0) { if (!success) { printable(line + 7, '?'); vstring_strcpy(reply, line + 7); } } } }
int main(int unused_argc, char **unused_argv) { VSTRING *in_buf = vstring_alloc(10); VSTRING *parse_buf = vstring_alloc(10); char *host; char *port; const char *err; while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) { vstream_printf(">> %s\n", STR(in_buf)); vstream_fflush(VSTREAM_OUT); if (*STR(in_buf) == '#') continue; vstring_strcpy(parse_buf, STR(in_buf)); if ((err = host_port(STR(parse_buf), &host, (char *) 0, &port, "default-service")) != 0) { msg_warn("%s in %s", err, STR(in_buf)); } else { vstream_printf("host %s port %s\n", host, port); vstream_fflush(VSTREAM_OUT); } } vstring_free(in_buf); vstring_free(parse_buf); return (0); }
char *fold_addr(VSTRING *result, const char *addr, int flags) { char *cp; /* * Fold the address as appropriate. */ switch (flags & FOLD_ADDR_ALL) { case FOLD_ADDR_HOST: if ((cp = strrchr(addr, '@')) != 0) { cp += 1; vstring_strncpy(result, addr, cp - addr); casefold_append(result, cp); break; } /* FALLTHROUGH */ case 0: vstring_strcpy(result, addr); break; case FOLD_ADDR_USER: if ((cp = strrchr(addr, '@')) != 0) { casefold_len(result, addr, cp - addr); vstring_strcat(result, cp); break; } /* FALLTHROUGH */ case FOLD_ADDR_USER | FOLD_ADDR_HOST: casefold(result, addr); break; } return (STR(result)); }
static int scache_single_find_endp(SCACHE *scache, const char *endp_label, VSTRING *endp_prop) { SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache; const char *myname = "scache_single_find_endp"; int fd; if (!SCACHE_SINGLE_ENDP_BUSY(sp)) { if (msg_verbose) msg_info("%s: no endpoint cache: %s", myname, endp_label); return (-1); } if (strcmp(STR(sp->endp.endp_label), endp_label) == 0) { vstring_strcpy(endp_prop, STR(sp->endp.endp_prop)); fd = sp->endp.fd; sp->endp.fd = -1; scache_single_free_endp(sp); if (msg_verbose) msg_info("%s: found: %s fd=%d", myname, endp_label, fd); return (fd); } if (msg_verbose) msg_info("%s: not found: %s", myname, endp_label); return (-1); }
int main(int argc, char **argv) { VSTRING *buf = vstring_alloc(100); MAPS *maps; msg_vstream_init(basename(argv[0]), VSTREAM_ERR); if (argc < 3) msg_fatal("usage: %s maptype:mapname address...", argv[0]); maps = maps_create(argv[1], argv[1], DICT_FLAG_FOLD_FIX); mail_params_init(); if (chdir(var_queue_dir) < 0) msg_fatal("chdir(%s): %m", var_queue_dir); argv += 1; msg_verbose = 1; while (--argc && *++argv) { msg_info("-- start %s --", *argv); smtp_map11_external(vstring_strcpy(buf, *argv), maps, 1); msg_info("-- end %s --", *argv); } vstring_free(buf); maps_free(maps); return (0); }
char *sane_dirname(VSTRING *bp, const char *path) { static VSTRING *buf; const char *last; /* * Your buffer or mine? */ if (bp == 0) { bp = buf; if (bp == 0) bp = buf = vstring_alloc(10); } /* * Special case: return "." for null or zero-length input. */ if (path == 0 || *path == 0) return (STR(vstring_strcpy(bp, "."))); /* * Remove trailing '/' characters from input. Return "/" if input is all * '/' characters. */ last = path + strlen(path) - 1; while (*last == '/') { if (last == path) return (STR(vstring_strcpy(bp, "/"))); last--; } /* * This pathname does not end in '/'. Skip to last '/' character if any. */ while (last >= path && *last != '/') last--; if (last < path) /* no '/' */ return (STR(vstring_strcpy(bp, "."))); /* * Strip trailing '/' characters from dirname (not strictly needed). */ while (last > path && *last == '/') last--; return (STR(vstring_strncpy(bp, path, last - path + 1))); }
static int xsasl_dovecot_server_next(XSASL_SERVER *xp, const char *request, VSTRING *reply) { XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp; if (!is_valid_base64(request)) { vstring_strcpy(reply, "Invalid base64 data in continued response"); return XSASL_AUTH_FAIL; } /* XXX Encapsulate for logging. */ vstream_fprintf(server->impl->sasl_stream, "CONT\t%u\t%s\n", server->last_request_id, request); if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) { vstring_strcpy(reply, "Connection lost to authentication server"); return XSASL_AUTH_TEMP; } return xsasl_dovecot_handle_reply(server, reply); }
int xsasl_cyrus_server_first(XSASL_SERVER *xp, const char *sasl_method, const char *init_response, VSTRING *reply) { const char *myname = "xsasl_cyrus_server_first"; XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; char *dec_buffer; unsigned dec_length; unsigned reply_len; unsigned serveroutlen; int sasl_status; SERVEROUT_TYPE serverout = 0; int xsasl_status; #if SASL_VERSION_MAJOR < 2 const char *errstr = 0; #endif #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3)) if (msg_verbose) msg_info("%s: sasl_method %s%s%s", myname, sasl_method, IFELSE(init_response, ", init_response ", ""), IFELSE(init_response, init_response, "")); /* * SASL authentication protocol start-up. Process any initial client * response that was sent along in the AUTH command. */ if (init_response) { reply_len = strlen(init_response); VSTRING_RESET(server->decoded); /* Fix 200512 */ VSTRING_SPACE(server->decoded, reply_len); if ((sasl_status = SASL_DECODE64(init_response, reply_len, dec_buffer = STR(server->decoded), vstring_avail(server->decoded), &dec_length)) != SASL_OK) { vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); return (XSASL_AUTH_FORM); } if (msg_verbose) msg_info("%s: decoded initial response %s", myname, dec_buffer); } else { dec_buffer = 0; dec_length = 0; } sasl_status = SASL_SERVER_START(server->sasl_conn, sasl_method, dec_buffer, dec_length, &serverout, &serveroutlen, &errstr); xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout, serveroutlen, reply); #if SASL_VERSION_MAJOR < 2 /* SASL version 1 doesn't free memory that it allocates. */ free(serverout); #endif return (xsasl_status); }
static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server, VSTRING *reply) { const char *myname = "xsasl_dovecot_handle_reply"; char *line, *cmd; /* XXX Encapsulate for logging. */ while (vstring_get_nonl(server->sasl_line, server->impl->sasl_stream) != VSTREAM_EOF) { line = vstring_str(server->sasl_line); if (msg_verbose) msg_info("%s: auth reply: %s", myname, line); cmd = line; line = split_at(line, '\t'); if (strcmp(cmd, "OK") == 0) { if (xsasl_dovecot_parse_reply(server, &line) == 0) { /* authentication successful */ xsasl_dovecot_parse_reply_args(server, line, reply, 1); return XSASL_AUTH_DONE; } } else if (strcmp(cmd, "CONT") == 0) { if (xsasl_dovecot_parse_reply(server, &line) == 0) { vstring_strcpy(reply, line); return XSASL_AUTH_MORE; } } else if (strcmp(cmd, "FAIL") == 0) { if (xsasl_dovecot_parse_reply(server, &line) == 0) { /* authentication failure */ xsasl_dovecot_parse_reply_args(server, line, reply, 0); return XSASL_AUTH_FAIL; } } else { /* ignore */ } } vstring_strcpy(reply, "Connection lost to authentication server"); return XSASL_AUTH_TEMP; }
const char *check_user_acl_byuid(char *acl, uid_t uid) { struct mypasswd *mypwd; STRING_LIST *list; static VSTRING *who = 0; int matched; const char *name; /* * Optimize for the most common case. This also makes Postfix a little * more robust in the face of local infrastructure failures. Note that we * only need to match the "static:" substring, not the result value. */ if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 0) return (0); /* * XXX: Substitute "unknown" for UIDs without username, so that * static:anyone results in "permit" even when the uid is not found in * the password file, and so that a pattern of !unknown can be used to * block non-existent accounts. * * The alternative is to use the UID as a surrogate lookup key for * non-existent accounts. There are several reasons why this is not a * good idea. 1) An ACL with a numerical UID should work regardless of * whether or not an account has a password file entry. Therefore we * would always have search on the numerical UID whenever the username * fails to produce a match. 2) The string-list infrastructure is not * really suitable for mixing numerical and non-numerical user * information, because the numerical match is done in a separate pass * from the non-numerical match. This breaks when the ! operator is used. * * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down) * invoke mypwuid_err(), and either change the user_acl() API to * propagate the error to the caller, or treat lookup errors as fatal. */ if ((mypwd = mypwuid(uid)) == 0) { name = "unknown"; } else { name = mypwd->pw_name; } list = string_list_init(MATCH_FLAG_NONE, acl); if ((matched = string_list_match(list, name)) == 0) { if (!who) who = vstring_alloc(10); vstring_strcpy(who, name); } string_list_free(list); if (mypwd) mypwfree(mypwd); return (matched ? 0 : vstring_str(who)); }
void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) { VSTRING *clean_addr = vstring_alloc(100); const char *bcc; /* * Note: an unqualified envelope address is for all practical purposes * equivalent to a fully qualified local address, both for delivery and * for replying. Having to support both forms is error prone, therefore * an incomplete envelope address is rewritten to fully qualified form in * the local domain context. * * 20000520: Replace mailer-daemon@$myorigin by the null address, to handle * bounced mail traffic more robustly. */ cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, clean_addr, buf); if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) vstring_strcpy(clean_addr, ""); } if (state->flags & CLEANUP_FLAG_MAP_OK) { if (cleanup_send_canon_maps && (cleanup_send_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_comm_canon_maps && (cleanup_comm_canon_flags & CLEANUP_CANON_FLAG_ENV_FROM)) cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); } CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); if (state->sender) /* XXX Can't happen */ myfree(state->sender); state->sender = mystrdup(STR(clean_addr)); /* Used by Milter client */ if ((state->flags & CLEANUP_FLAG_BCC_OK) && *STR(clean_addr) && cleanup_send_bcc_maps) { if ((bcc = mail_addr_find(cleanup_send_bcc_maps, STR(clean_addr), IGNORE_EXTENSION)) != 0) { cleanup_addr_bcc(state, bcc); } else if (cleanup_send_bcc_maps->error) { msg_warn("%s: %s map lookup problem -- " "message not accepted, try again later", state->queue_id, cleanup_send_bcc_maps->title); state->errs |= CLEANUP_STAT_WRITE; } } vstring_free(clean_addr); }
static int xsasl_cyrus_server_auth_response(int sasl_status, SERVEROUT_TYPE serverout, unsigned serveroutlen, VSTRING *reply) { const char *myname = "xsasl_cyrus_server_auth_response"; unsigned enc_length; unsigned enc_length_out; /* * Encode the server first/next non-error response; otherwise return the * unencoded error text that corresponds to the SASL error status. * * Regarding the hairy expression below: output from sasl_encode64() comes * in multiples of four bytes for each triple of input bytes, plus four * bytes for any incomplete last triple, plus one byte for the null * terminator. */ if (sasl_status == SASL_OK) { vstring_strcpy(reply, ""); return (XSASL_AUTH_DONE); } else if (sasl_status == SASL_CONTINUE) { if (msg_verbose) msg_info("%s: uncoded server challenge: %.*s", myname, (int) serveroutlen, serverout); enc_length = ((serveroutlen + 2) / 3) * 4 + 1; VSTRING_RESET(reply); /* Fix 200512 */ VSTRING_SPACE(reply, enc_length); if ((sasl_status = sasl_encode64(serverout, serveroutlen, STR(reply), vstring_avail(reply), &enc_length_out)) != SASL_OK) msg_panic("%s: sasl_encode64 botch: %s", myname, xsasl_cyrus_strerror(sasl_status)); return (XSASL_AUTH_MORE); } else { if (sasl_status == SASL_NOUSER) /* privacy */ sasl_status = SASL_BADAUTH; vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); return (XSASL_AUTH_FAIL); } }
char *sane_basename(VSTRING *bp, const char *path) { static VSTRING *buf; const char *first; const char *last; /* * Your buffer or mine? */ if (bp == 0) { bp = buf; if (bp == 0) bp = buf = vstring_alloc(10); } /* * Special case: return "." for null or zero-length input. */ if (path == 0 || *path == 0) return (STR(vstring_strcpy(bp, "."))); /* * Remove trailing '/' characters from input. Return "/" if input is all * '/' characters. */ last = path + strlen(path) - 1; while (*last == '/') { if (last == path) return (STR(vstring_strcpy(bp, "/"))); last--; } /* * The pathname does not end in '/'. Skip to last '/' character if any. */ first = last - 1; while (first >= path && *first != '/') first--; return (STR(vstring_strncpy(bp, first + 1, last - first))); }
static void scache_single_save_endp(SCACHE *scache, int endp_ttl, const char *endp_label, const char *endp_prop, int fd) { SCACHE_SINGLE *sp = (SCACHE_SINGLE *) scache; const char *myname = "scache_single_save_endp"; if (endp_ttl <= 0) msg_panic("%s: bad endp_ttl: %d", myname, endp_ttl); if (SCACHE_SINGLE_ENDP_BUSY(sp)) scache_single_free_endp(sp); /* dump the cached fd */ vstring_strcpy(sp->endp.endp_label, endp_label); vstring_strcpy(sp->endp.endp_prop, endp_prop); sp->endp.fd = fd; event_request_timer(scache_single_expire_endp, (char *) sp, endp_ttl); if (msg_verbose) msg_info("%s: %s fd=%d", myname, endp_label, fd); }
int rewrite_proto(VSTREAM *stream) { RWR_CONTEXT *context; TOK822 *tree; if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_RULE, ruleset, ATTR_TYPE_STR, MAIL_ATTR_ADDR, address, ATTR_TYPE_END) != 2) return (-1); if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_LOCAL) == 0) context = &local_context; else if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_REMOTE) == 0) context = &remote_context; else { msg_warn("unknown context: %s", vstring_str(ruleset)); return (-1); } /* * Sanity check. An address is supposed to be in externalized form. */ if (*vstring_str(address) == 0) { msg_warn("rewrite_addr: null address"); vstring_strcpy(result, vstring_str(address)); } /* * Convert the address from externalized (quoted) form to token list, * rewrite it, and convert back. */ else { tree = tok822_scan_addr(vstring_str(address)); rewrite_tree(context, tree); tok822_externalize(result, tree, TOK822_STR_DEFL); tok822_free_tree(tree); } if (msg_verbose) msg_info("`%s' `%s' -> `%s'", vstring_str(ruleset), vstring_str(address), vstring_str(result)); attr_print(stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, server_flags, ATTR_TYPE_STR, MAIL_ATTR_ADDR, vstring_str(result), ATTR_TYPE_END); if (vstream_fflush(stream) != 0) { msg_warn("write rewrite reply: %m"); return (-1); } return (0); }
static const char *dict_env_lookup(DICT *dict, const char *name) { dict->error = 0; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } return (safe_getenv(name)); }
static const char *dict_ht_lookup(DICT *dict, const char *name) { DICT_HT *dict_ht = (DICT_HT *) dict; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name)); }
static void morph_recipient(VSTRING *buf, const char *address, int flags) { /* * Quote the recipient address as appropriate. */ if (flags & PIPE_OPT_QUOTE_LOCAL) quote_822_local(buf, address); else vstring_strcpy(buf, address); /* * Fold the recipient address as appropriate. */ if (flags & PIPE_OPT_FOLD_ALL) fold_addr(STR(buf), PIPE_OPT_FOLD_FLAGS(flags)); }
const char *fullname(void) { static VSTRING *result; char *cp; int ch; uid_t uid; struct passwd *pwd; if (result == 0) result = vstring_alloc(10); /* * Try the environment. */ if ((cp = safe_getenv("NAME")) != 0) return (vstring_str(vstring_strcpy(result, cp))); /* * Try the password file database. */ uid = getuid(); if ((pwd = getpwuid(uid)) == 0) return (0); /* * Replace all `&' characters by the login name of this user, first * letter capitalized. Although the full name comes from the protected * password file, the actual data is specified by the user so we should * not trust its sanity. */ VSTRING_RESET(result); for (cp = pwd->pw_gecos; (ch = *(unsigned char *) cp) != 0; cp++) { if (ch == ',' || ch == ';' || ch == '%') break; if (ch == '&') { if (pwd->pw_name[0]) { VSTRING_ADDCH(result, TOUPPER(pwd->pw_name[0])); vstring_strcat(result, pwd->pw_name + 1); } } else { VSTRING_ADDCH(result, ch); } } VSTRING_TERMINATE(result); return (vstring_str(result)); }
static void pcf_gobble_cf_line(VSTRING *full_entry_buf, VSTRING *line_buf, VSTREAM *src, VSTREAM *dst, int *lineno) { int ch; vstring_strcpy(full_entry_buf, STR(line_buf)); for (;;) { if ((ch = VSTREAM_GETC(src)) != VSTREAM_EOF) vstream_ungetc(src, ch); if ((ch != '#' && !ISSPACE(ch)) || vstring_get(line_buf, src) == VSTREAM_EOF) break; lineno += 1; if (pcf_find_cf_info(line_buf, dst)) vstring_strcat(full_entry_buf, STR(line_buf)); } }
char *data_redirect_map(VSTRING *result, const char *map) { const char *path; const char *map_type; size_t map_type_len; #define MAP_DELIMITER ":" /* * Sanity check. */ if (map == STR(result)) msg_panic("data_redirect_map: result clobbers input"); /* * Parse the input into map type and map name. */ path = strchr(map, MAP_DELIMITER[0]); if (path != 0) { map_type = map; map_type_len = path - map; path += 1; } else { map_type = var_db_type; map_type_len = strlen(map_type); path = map; } /* * Redirect the pathname. */ vstring_strncpy(result, map_type, map_type_len); if (name_code(data_redirect_map_types, NAME_CODE_FLAG_NONE, STR(result))) { data_redirect_path(result, path, "table", map); } else { vstring_strcpy(result, path); } /* * (Re)combine the map type with the map name. */ vstring_prepend(result, MAP_DELIMITER, sizeof(MAP_DELIMITER) - 1); vstring_prepend(result, map_type, map_type_len); return (STR(result)); }
static int dict_env_update(DICT *dict, const char *name, const char *value) { dict->error = 0; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } if (setenv(name, value, 1)) msg_fatal("setenv: %m"); return (DICT_STAT_SUCCESS); }
int cleanup_map11_external(CLEANUP_STATE *state, VSTRING *addr, MAPS *maps, int propagate) { int count; int expand_to_self; ARGV *new_addr; char *saved_addr; int did_rewrite = 0; /* * Produce sensible output even in the face of a recoverable error. This * simplifies error recovery considerably because we can do delayed error * checking in one place, instead of having error handling code all over * the place. */ for (count = 0; count < MAX_RECURSION; count++) { if ((new_addr = mail_addr_map(maps, STR(addr), propagate)) != 0) { if (new_addr->argc > 1) msg_warn("%s: multi-valued %s entry for %s", state->queue_id, maps->title, STR(addr)); saved_addr = mystrdup(STR(addr)); did_rewrite |= strcmp(new_addr->argv[0], STR(addr)); vstring_strcpy(addr, new_addr->argv[0]); expand_to_self = !strcasecmp_utf8(saved_addr, STR(addr)); myfree(saved_addr); argv_free(new_addr); if (expand_to_self) return (did_rewrite); } else if (maps->error != 0) { msg_warn("%s: %s map lookup problem for %s -- " "message not accepted, try again later", state->queue_id, maps->title, STR(addr)); state->errs |= CLEANUP_STAT_WRITE; return (did_rewrite); } else { return (did_rewrite); } } msg_warn("%s: unreasonable %s map nesting for %s -- " "message not accepted, try again later", state->queue_id, maps->title, STR(addr)); return (did_rewrite); }
static int verify_cache_validator(const char *addr, const char *raw_data, void *context) { VSTRING *get_buf = (VSTRING *) context; int addr_status; long probed; long updated; char *text; long now = (long) event_time(); #define POS_OR_NEG_ENTRY_EXPIRED(stat, stamp) \ (POSITIVE_ENTRY_EXPIRED((stat), (stamp)) \ || NEGATIVE_ENTRY_EXPIRED((stat), (stamp))) vstring_strcpy(get_buf, raw_data); return (verify_parse_entry(STR(get_buf), &addr_status, /* syntax OK */ &probed, &updated, &text) == 0 && (now - probed < PROBE_TTL /* probe in progress */ || !POS_OR_NEG_ENTRY_EXPIRED(addr_status, updated))); }
static int xsasl_cyrus_server_next(XSASL_SERVER *xp, const char *request, VSTRING *reply) { const char *myname = "xsasl_cyrus_server_next"; XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp; unsigned dec_length; unsigned request_len; unsigned serveroutlen; int sasl_status; SERVEROUT_TYPE serverout = 0; int xsasl_status; #if SASL_VERSION_MAJOR < 2 const char *errstr = 0; #endif request_len = strlen(request); VSTRING_RESET(server->decoded); /* Fix 200512 */ VSTRING_SPACE(server->decoded, request_len); if ((sasl_status = SASL_DECODE64(request, request_len, STR(server->decoded), vstring_avail(server->decoded), &dec_length)) != SASL_OK) { vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status)); return (XSASL_AUTH_FORM); } if (msg_verbose) msg_info("%s: decoded response: %.*s", myname, (int) dec_length, STR(server->decoded)); sasl_status = SASL_SERVER_STEP(server->sasl_conn, STR(server->decoded), dec_length, &serverout, &serveroutlen, &errstr); xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout, serveroutlen, reply); #if SASL_VERSION_MAJOR < 2 /* SASL version 1 doesn't free memory that it allocates. */ free(serverout); #endif return (xsasl_status); }
static char *data_redirect_path(VSTRING *result, const char *path, const char *log_type, const char *log_name) { struct stat st; #define PATH_DELIMITER "/" (void) sane_dirname(result, path); if (stat(STR(result), &st) != 0 || st.st_uid == var_owner_uid) { vstring_strcpy(result, path); } else { msg_warn("request to update %s %s in non-%s directory %s", log_type, log_name, var_mail_owner, STR(result)); msg_warn("redirecting the request to %s-owned %s %s", var_mail_owner, VAR_DATA_DIR, var_data_dir); (void) sane_basename(result, path); vstring_prepend(result, PATH_DELIMITER, sizeof(PATH_DELIMITER) - 1); vstring_prepend(result, var_data_dir, strlen(var_data_dir)); } return (STR(result)); }
void msg_text(int level, const char *text) { int i; /* * Sanitize the text. Use a private copy if necessary. */ if (msg_text_lock == 0) { msg_text_lock = 1; /* OK if terminating signal handler hijacks control before next stmt. */ if (text != vstring_str(msg_buffer)) vstring_strcpy(msg_buffer, text); printable(vstring_str(msg_buffer), '?'); /* On-the-fly initialization for debugging test programs only. */ if (msg_output_fn_count == 0) msg_vstream_init("unknown", VSTREAM_ERR); for (i = 0; i < msg_output_fn_count; i++) msg_output_fn[i] (level, vstring_str(msg_buffer)); msg_text_lock = 0; } }
static const char * dict_erlang_lookup(DICT *dict, const char *key) { int ret; char *res; const char *myname = "dict_erlang_lookup"; DICT_ERLANG *dict_erlang = (DICT_ERLANG *)dict; dict_erlang->dict.error = 0; if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == NULL) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, key); key = lowercase(vstring_str(dict->fold_buf)); } if (db_common_check_domain(dict_erlang->ctx, key) == 0) { if (msg_verbose) msg_info("%s: Skipping lookup of '%s'", myname, key); return 0; } ret = erlang_query(dict_erlang, key, dict_erlang->nodes, dict_erlang->cookie, dict_erlang->mod, dict_erlang->fun, &res); switch (ret) { case -1: dict_erlang->dict.error = DICT_ERR_RETRY; return NULL; case 0: /* Not found */ return NULL; case 1: return res; default: msg_warn("unexpected query result"); return NULL; } }