Beispiel #1
0
static int verify_parse_entry(char *buf, int *status, long *probed,
			              long *updated, char **text)
{
    char   *probed_text;
    char   *updated_text;

    if ((probed_text = split_at(buf, ':')) != 0
	&& (updated_text = split_at(probed_text, ':')) != 0
	&& (*text = split_at(updated_text, ':')) != 0
	&& alldig(buf)
	&& alldig(probed_text)
	&& alldig(updated_text)) {
	*probed = atol(probed_text);
	*updated = atol(updated_text);
	*status = atoi(buf);

	/*
	 * Coverity 200604: the code incorrectly tested (probed || updated),
	 * so that the sanity check never detected all-zero time stamps. Such
	 * records are never written. If we read a record with all-zero time
	 * stamps, then something is badly broken.
	 */
	if ((*status == DEL_RCPT_STAT_OK
	     || *status == DEL_RCPT_STAT_DEFER
	     || *status == DEL_RCPT_STAT_BOUNCE
	     || *status == DEL_RCPT_STAT_TODO)
	    && (*probed || *updated))
	    return (0);
    }
    msg_warn("bad address verify table entry: %.100s", buf);
    return (-1);
}
int main(){
    char * num1 ;
    char * num2 ;
    num1 = readInput(1);
    num2 = readInput(2);

    printf("\nConverted to int:%d",convert_to_int(num1));
    printf("\nConverted to char:%s",convert_to_char(convert_to_int(num1)));
    printf("\nMax:%d",max(num1,num2,10));
    printf("\nSplit at 0-3:%s",split_at(num1,0,3));
    printf("\nSplit at 3-5:%s",split_at(num1,3,strlen(num1)));
    printf("\nKaratsuba:%d",karatSuba(num1,num2));

    return 0 ;
}
Beispiel #3
0
static int find_transport_entry(TRANSPORT_INFO *tp, const char *key,
				        const char *rcpt_domain, int flags,
				        VSTRING *channel, VSTRING *nexthop)
{
    char   *saved_value;
    const char *host;
    const char *value;

#define FOUND		1
#define NOTFOUND	0

    /*
     * Look up an entry with extreme prejudice.
     * 
     * XXX Should report lookup failure status to caller instead of aborting.
     */
    if ((value = maps_find(tp->transport_path, key, flags)) == 0)
	return (NOTFOUND);

    /*
     * It would be great if we could specify a recipient address in the
     * lookup result. Unfortunately, we cannot simply run the result through
     * a parser that recognizes "transport:user@domain" because the lookup
     * result can have arbitrary content (especially in the case of the error
     * mailer).
     */
    else {
	saved_value = mystrdup(value);
	host = split_at(saved_value, ':');
	update_entry(saved_value, host ? host : "", rcpt_domain,
		     channel, nexthop);
	myfree(saved_value);
	return (FOUND);
    }
}
static void
banners_option(char *value, struct request_info *request)
{
    char    path[MAXPATHLEN];
    char    ibuf[BUFSIZ];
    char    obuf[2 * BUFSIZ];
    struct stat st;
    int     ch;
    FILE   *fp;

    (void)snprintf(path, sizeof path, "%s/%s", value, eval_daemon(request));
    if ((fp = fopen(path, "r")) != 0) {
	while ((ch = fgetc(fp)) == 0)
	    write(request->fd, "", 1);
	ungetc(ch, fp);
	while (fgets(ibuf, sizeof(ibuf) - 2, fp)) {
	    if (split_at(ibuf, '\n'))
		strcat(ibuf, "\r\n");	/* XXX strcat is safe */
	    percent_x(obuf, sizeof(obuf), ibuf, request);
	    write(request->fd, obuf, strlen(obuf));
	}
	fclose(fp);
    } else if (stat(value, &st) < 0) {
	tcpd_warn("%s: %m", value);
    }
}
Beispiel #5
0
int     smtp_sasl_passwd_lookup(SMTP_SESSION *session)
{
    const char *myname = "smtp_sasl_passwd_lookup";
    SMTP_STATE *state = session->state;
    const char *value;
    char   *passwd;

    /*
     * Sanity check.
     */
    if (smtp_sasl_passwd_map == 0)
	msg_panic("%s: passwd map not initialized", myname);

    /*
     * Look up the per-server password information. Try the hostname first,
     * then try the destination.
     * 
     * XXX Instead of using nexthop (the intended destination) we use dest
     * (either the intended destination, or a fall-back destination).
     * 
     * XXX SASL authentication currently depends on the host/domain but not on
     * the TCP port. If the port is not :25, we should append it to the table
     * lookup key. Code for this was briefly introduced into 2.2 snapshots,
     * but didn't canonicalize the TCP port, and did not append the port to
     * the MX hostname.
     */
    smtp_sasl_passwd_map->error = 0;
    if (((state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0
	 && var_smtp_sender_auth && state->request->sender[0]
	 && (value = mail_addr_find(smtp_sasl_passwd_map,
				 state->request->sender, (char **) 0)) != 0)
	|| (smtp_sasl_passwd_map->error == 0
	    && (value = maps_find(smtp_sasl_passwd_map,
				  session->host, 0)) != 0)
	|| (smtp_sasl_passwd_map->error == 0
	    && (value = maps_find(smtp_sasl_passwd_map,
				  session->dest, 0)) != 0)) {
	if (session->sasl_username)
	    myfree(session->sasl_username);
	session->sasl_username = mystrdup(value);
	passwd = split_at(session->sasl_username, ':');
	if (session->sasl_passwd)
	    myfree(session->sasl_passwd);
	session->sasl_passwd = mystrdup(passwd ? passwd : "");
	if (msg_verbose)
	    msg_info("%s: host `%s' user `%s' pass `%s'",
		     myname, session->host,
		     session->sasl_username, session->sasl_passwd);
	return (1);
    } else if (smtp_sasl_passwd_map->error) {
	msg_warn("%s: %s lookup error",
		  state->request->queue_id, smtp_sasl_passwd_map->title);
	vstream_longjmp(session->stream, SMTP_ERR_DATA);
    } else {
	if (msg_verbose)
	    msg_info("%s: no auth info found (sender=`%s', host=`%s')",
		     myname, state->request->sender, session->host);
	return (0);
    }
}
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);
	    }
	}
    }
}
void VG_(bindRangeMap) ( RangeMap* rm,
                         UWord key_min, UWord key_max, UWord val )
{
   vg_assert(key_min <= key_max);
   split_at(rm, key_min);
   if (key_max < UWORD_MAX)
      split_at(rm, key_max + 1);
   Word iMin, iMax, i;
   iMin = find(rm, key_min);
   iMax = find(rm, key_max);
   for (i = iMin; i <= iMax; i++) {
      Range* rng = VG_(indexXA)(rm->ranges, i);
      rng->val = val;
   }
   preen(rm);
}
Beispiel #8
0
int     main(int argc, char **argv)
{
    char   *transport;
    char   *endpoint;
    char   *path;
    int     server_sock;
    int     client_fd;

    if (argc < 3
	|| (endpoint = split_at(transport = argv[1], ':')) == 0
	|| *endpoint == 0 || *transport == 0)
	msg_fatal("usage: %s transport:endpoint file...", argv[0]);

    if (strcmp(transport, "stream") == 0) {
	server_sock = stream_connect(endpoint, BLOCKING, 0);
    } else {
	msg_fatal("invalid transport name: %s", transport);
    }
    if (server_sock < 0)
	msg_fatal("connect %s:%s: %m", transport, endpoint);

    argv += 2;
    while ((path = *argv++) != 0) {
	if ((client_fd = open(path, O_RDONLY, 0)) < 0)
	    msg_fatal("open %s: %m", path);
	msg_info("path=%s client_fd=%d", path, client_fd);
	if (stream_send_fd(server_sock, client_fd) < 0)
	    msg_fatal("send file descriptor: %m");
	if (close(client_fd) != 0)
	    msg_fatal("close(%d): %m", client_fd);
    }
    exit(0);
}
Beispiel #9
0
static void postmap_body(void *ptr, int unused_rec_type,
			         const char *keybuf,
			         ssize_t unused_len,
			         off_t unused_offset)
{
    POSTMAP_KEY_STATE *state = (POSTMAP_KEY_STATE *) ptr;
    DICT  **dicts = state->dicts;
    char  **maps = state->maps;
    int     map_count = state->map_count;
    int     dict_flags = state->dict_flags;
    const char *map_name;
    const char *value;
    int     n;

    for (n = 0; n < map_count; n++) {
	if (dicts[n] == 0)
	    dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
			dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
		    dict_open3(var_db_type, maps[n], O_RDONLY, dict_flags));
	if ((value = dict_get(dicts[n], keybuf)) != 0) {
	    if (*value == 0) {
		msg_warn("table %s:%s: key %s: empty string result is not allowed",
			 dicts[n]->type, dicts[n]->name, keybuf);
		msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
			 dicts[n]->type, dicts[n]->name);
	    }
	    vstream_printf("%s	%s\n", keybuf, value);
	    state->found = 1;
	    break;
	}
	if (dicts[n]->error)
	    msg_fatal("table %s:%s: query error: %m",
		      dicts[n]->type, dicts[n]->name);
    }
}
Beispiel #10
0
char   *split_addr(char *localpart, int delimiter)
{
    int     len;

    /*
     * Don't split these, regardless of what the delimiter is.
     */
    if (strcasecmp(localpart, MAIL_ADDR_POSTMASTER) == 0)
	return (0);
    if (strcasecmp(localpart, MAIL_ADDR_MAIL_DAEMON) == 0)
	return (0);
    if (strcasecmp(localpart, var_double_bounce_sender) == 0)
	return (0);

    /*
     * Backwards compatibility: don't split owner-foo or foo-request.
     */
    if (delimiter == '-' && var_ownreq_special != 0) {
	if (strncasecmp(localpart, "owner-", 6) == 0)
	    return (0);
	if ((len = strlen(localpart) - 8) > 0
	    && strcasecmp(localpart + len, "-request") == 0)
	    return (0);
    }

    /*
     * Safe to split this address. Do not split the address if the result
     * would have a null localpart.
     */
    return (delimiter == *localpart ? 0 : split_at(localpart, delimiter));
}
Beispiel #11
0
void    register_dbms_parameters(const char *param_value,
          const char *(flag_parameter) (const char *, int, PC_MASTER_ENT *),
				         PC_MASTER_ENT *local_scope)
{
    const PC_DBMS_INFO *dp;
    char   *bufp;
    char   *db_type;
    char   *prefix;
    static VSTRING *buffer = 0;
    static VSTRING *candidate = 0;
    const char **cpp;

    /*
     * XXX This does not examine both sides of conditional macro expansion,
     * and may expand the "wrong" conditional macros. This is the best we can
     * do for legacy database configuration support.
     */
    if (buffer == 0)
	buffer = vstring_alloc(100);
    bufp = expand_parameter_value(buffer, SHOW_EVAL, param_value, local_scope);

    /*
     * Naive parsing. We don't really know if the parameter specifies free
     * text or a list of databases.
     */
    while ((db_type = mystrtok(&bufp, " ,\t\r\n")) != 0) {

	/*
	 * Skip over "proxy:" maptypes, to emulate the proxymap(8) server's
	 * behavior when opening a local database configuration file.
	 */
	while ((prefix = split_at(db_type, ':')) != 0
	       && strcmp(db_type, DICT_TYPE_PROXY) == 0)
	    db_type = prefix;

	/*
	 * Look for database:prefix where the prefix is not a pathname and
	 * the database is a known type. Synthesize candidate parameter names
	 * from the user-defined prefix and from the database-defined suffix
	 * list, and see if those parameters have a "name=value" entry in the
	 * local or global namespace.
	 */
	if (prefix != 0 && *prefix != '/' && *prefix != '.') {
	    for (dp = dbms_info; dp->db_type != 0; dp++) {
		if (strcmp(db_type, dp->db_type) == 0) {
		    for (cpp = dp->db_suffixes; *cpp; cpp++) {
			vstring_sprintf(candidate ? candidate :
					(candidate = vstring_alloc(30)),
					"%s_%s", prefix, *cpp);
			flag_parameter(STR(candidate),
				    PC_PARAM_FLAG_DBMS | PC_PARAM_FLAG_USER,
				       local_scope);
		    }
		    break;
		}
	    }
	}
    }
}
static void
severity_option(char *value, struct request_info *request)
{
    char   *level = split_at(value, '.');

    allow_severity = deny_severity = level ?
	severity_map(log_fac, value) | severity_map(log_sev, level) :
	severity_map(log_sev, value);
}
Beispiel #13
0
static const char *mail_version_worker(MAIL_VERSION *mp, char *cp)
{
    char   *major_field;
    char   *minor_field;
    char   *patch_field;

    /*
     * Program name.
     */
    if ((mp->program = mystrtok(&cp, "-")) == 0)
	return ("no program name");

    /*
     * Major, minor, patchlevel. If this is a stable release, then we ignore
     * text after the patchlevel, in case there are vendor extensions.
     */
    if ((major_field = mystrtok(&cp, "-")) == 0)
	return ("missing major version");

    if ((minor_field = split_at(major_field, '.')) == 0)
	return ("missing minor version");
    if ((mp->major = mail_version_int(major_field)) < 0)
	return ("bad major version");
    patch_field = split_at(minor_field, '.');
    if ((mp->minor = mail_version_int(minor_field)) < 0)
	return ("bad minor version");

    if (patch_field == 0)
	mp->patch = -1;
    else if ((mp->patch = mail_version_int(patch_field)) < 0)
	return ("bad patchlevel");

    /*
     * Experimental release. If this is not a stable release, we take
     * everything to the end of the string.
     */
    if (patch_field != 0)
	mp->snapshot = 0;
    else if ((mp->snapshot = mystrtok(&cp, "")) == 0)
	return ("missing snapshot field");

    return (0);
}
Beispiel #14
0
static int postmap_deletes(VSTREAM *in, char **maps, const int map_count,
			           int dict_flags)
{
    int     found = 0;
    VSTRING *keybuf = vstring_alloc(100);
    DICT  **dicts;
    const char *map_name;
    int     n;
    int     open_flags;

    /*
     * Sanity check.
     */
    if (map_count <= 0)
	msg_panic("postmap_deletes: bad map count");

    /*
     * Open maps ahead of time.
     */
    dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
    for (n = 0; n < map_count; n++) {
	map_name = split_at(maps[n], ':');
	if (map_name && strcmp(maps[n], DICT_TYPE_PROXY) == 0)
	    open_flags = O_RDWR | O_CREAT;	/* XXX */
	else
	    open_flags = O_RDWR;
	dicts[n] = (map_name != 0 ?
		    dict_open3(maps[n], map_name, open_flags, dict_flags) :
		  dict_open3(var_db_type, maps[n], open_flags, dict_flags));
    }

    /*
     * Perform all requests.
     */
    while (vstring_get_nonl(keybuf, in) != VSTREAM_EOF) {
	for (n = 0; n < map_count; n++) {
	    found |= (dict_del(dicts[n], STR(keybuf)) == 0);
	    if (dicts[n]->error)
		msg_fatal("table %s:%s: delete error: %m",
			  dicts[n]->type, dicts[n]->name);
	}
    }

    /*
     * Cleanup.
     */
    for (n = 0; n < map_count; n++)
	if (dicts[n])
	    dict_close(dicts[n]);
    myfree((void *) dicts);
    vstring_free(keybuf);

    return (found);
}
int karatSuba( char * num1, char * num2 ){
    int n1,n2 ;
    n1 = convert_to_int(num1);
    n2 = convert_to_int(num2);

    if ( n1 < 10 || n2 < 10 ){
        return n1*n2 ;
    }
    int m = max(num1,num2,10)/2;

    // high1, low1 = split_at(num1,m2);
    char * high1 = split_at(num1,0,m);
    char * low1 = split_at(num1,m,strlen(num1));
    // high2, low2 = split_at(num2,m2);
    char * high2 = split_at(num2,0,m);
    char * low2 = split_at(num2,m,strlen(num2));

    int z0 = karatSuba(low1,low2);
    int z1 = karatSuba(convert_to_char(convert_to_int(low1)+convert_to_int(high1)),(convert_to_char(convert_to_int(low2)+convert_to_int(high2))));
    int z2 = karatSuba(high1,high2);
    return (z2*pow(10,2*m))+((z1-z2-z0)*pow(10,m))+z0;
}
Beispiel #16
0
DICT   *dict_open(const char *dict_spec, int open_flags, int dict_flags)
{
    char   *saved_dict_spec = mystrdup(dict_spec);
    char   *dict_name;
    DICT   *dict;

    if ((dict_name = split_at(saved_dict_spec, ':')) == 0)
	msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s\"",
		  dict_spec);

    dict = dict_open3(saved_dict_spec, dict_name, open_flags, dict_flags);
    myfree(saved_dict_spec);
    return (dict);
}
static void
user_option(char *value, struct request_info *request)
{
    struct passwd *pwd, pws;
    char   *group;
    char   pwbuf[1024];

    if ((group = split_at(value, '.')) != 0)
	group_option(group, request);
    (void)getpwnam_r(value, &pws, pwbuf, sizeof(pwbuf), &pwd);
    if (pwd == NULL)
	tcpd_jump("unknown user: \"%s\"", value);

    if (dry_run == 0 && setuid(pwd->pw_uid))
	tcpd_jump("setuid(%s): %m", value);
}
Beispiel #18
0
int     main(int argc, char **argv)
{
    VSTRING *reply;
    int     ch;
    char   *rule;
    char   *addr;

    msg_vstream_init(argv[0], VSTREAM_ERR);

    mail_conf_read();
    msg_info("using config files in %s", var_config_dir);
    if (chdir(var_queue_dir) < 0)
	msg_fatal("chdir %s: %m", var_queue_dir);

    while ((ch = GETOPT(argc, argv, "v")) > 0) {
	switch (ch) {
	case 'v':
	    msg_verbose++;
	    break;
	default:
	    usage(argv[0]);
	}
    }
    reply = vstring_alloc(1);

    if (argc > optind) {
	for (;;) {
	    if ((rule = argv[optind++]) == 0)
		break;
	    if ((addr = argv[optind++]) == 0)
		usage(argv[0]);
	    rewrite(rule, addr, reply);
	}
    } else {
	VSTRING *buffer = vstring_alloc(1);

	while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
	    if ((addr = split_at(STR(buffer), ' ')) == 0
		|| *(rule = STR(buffer)) == 0)
		usage(argv[0]);
	    rewrite(rule, addr, reply);
	}
	vstring_free(buffer);
    }
    vstring_free(reply);
    exit(0);
}
static int xsasl_dovecot_parse_reply(XSASL_DOVECOT_SERVER *server, char **line)
{
    char   *id;

    if (*line == NULL) {
	msg_warn("SASL: Protocol error");
	return -1;
    }
    id = *line;
    *line = split_at(*line, '\t');

    if (strtoul(id, NULL, 0) != server->last_request_id) {
	/* reply to another request, shouldn't really happen.. */
	return -1;
    }
    return 0;
}
Beispiel #20
0
const char *host_port(char *buf, char **host, char *def_host,
		              char **port, char *def_service)
{
    char   *cp = buf;

    /*
     * [host]:port, [host]:, [host].
     */
    if (*cp == '[') {
	*host = ++cp;
	if ((cp = split_at(cp, ']')) == 0)
	    return ("missing \"]\"");
	if (*cp && *cp++ != ':')
	    return ("garbage after \"]\"");
	*port = *cp ? cp : def_service;
    }

    /*
     * host:port, host:, host, :port, port.
     */
    else {
	if ((cp = split_at_right(buf, ':')) != 0) {
	    *host = *buf ? buf : def_host;
	    *port = *cp ? cp : def_service;
	} else {
	    *host = def_host ? def_host : (*buf ? buf : 0);
	    *port = def_service ? def_service : (*buf ? buf : 0);
	}
    }
    if (*host == 0)
	return ("missing host information");
    if (*port == 0)
	return ("missing service information");

    /*
     * Final sanity checks. We're still sloppy, allowing bare numerical
     * network addresses instead of requiring proper [ipaddress] forms.
     */
    if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
	&& !valid_hostaddr(*host, DONT_GRIPE))
	return ("valid hostname or network address required");
    if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
	return ("garbage after numerical service");
    return (0);
}
Beispiel #21
0
static int match_parse_mask(const char *pattern, unsigned long *net_bits,
			            unsigned int *mask_shift)
{
    char   *saved_pattern;
    char   *mask;

#define BITS_PER_ADDR	32

    saved_pattern = mystrdup(pattern);
    if ((mask = split_at(saved_pattern, '/')) != 0) {
	if (!alldig(mask) || (*mask_shift = atoi(mask)) > BITS_PER_ADDR
	    || (*net_bits = inet_addr(saved_pattern)) == INADDR_NONE) {
	    msg_fatal("bad net/mask pattern: %s", pattern);
	}
    }
    myfree(saved_pattern);
    return (mask != 0);
}
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;
}
Beispiel #23
0
Datei: r.c Projekt: wpwrak/subosm
static double split(int a, int b)
{
	enum class ca, cb;

	ca = classify(a);
	cb = classify(b);

	if (ca == cb)
		return 0.5;
	if (ca > cb)
		return 1.0-split(b, a);

	switch (ca) {
	case good:
		switch (cb) {
		case average:
			return split_at(333, a, b);
		case bad:
			return split_at(500, a, b);
		case remote:
			return split_at(999, a, b);
		default:
			abort();
		}
	case average:
		switch (cb) {
		case bad:
			return split_at(666, a, b);
		case remote:
			return split_at(999, a, b);
		default:
			abort();
		}
	case bad:
		switch (cb) {
		case remote:
			return split_at(1000, a, b);
		default:
			abort();
		}
	default:
		abort();
	}
}
Beispiel #24
0
static void output_header(void *context, int header_class,
			          const HEADER_OPTS *header_info,
			          VSTRING *buf, off_t offset)
{
    SM_STATE *state = (SM_STATE *) context;
    TOK822 *tree;
    TOK822 **addr_list;
    TOK822 **tpp;
    ARGV   *rcpt;
    char   *start;
    char   *line;
    char   *next_line;
    ssize_t len;

    /*
     * Parse the header line, and save copies of recipient addresses in the
     * appropriate place.
     */
    if (header_class == MIME_HDR_PRIMARY
	&& header_info
	&& (header_info->flags & HDR_OPT_RECIP)
	&& (header_info->flags & HDR_OPT_EXTRACT)
	&& (state->resent == 0 || (header_info->flags & HDR_OPT_RR))) {
	if (header_info->flags & HDR_OPT_RR) {
	    rcpt = state->resent_recip;
	    if (state->resent == 0)
		state->resent = 1;
	} else
	    rcpt = state->recipients;
	tree = tok822_parse(STR(buf) + strlen(header_info->name) + 1);
	addr_list = tok822_grep(tree, TOK822_ADDR);
	for (tpp = addr_list; *tpp; tpp++) {
	    tok822_internalize(state->temp, tpp[0]->head, TOK822_STR_DEFL);
	    argv_add(rcpt, STR(state->temp), (char *) 0);
	}
	myfree((void *) addr_list);
	tok822_free_tree(tree);
    }

    /*
     * Pipe the unmodified message header through the header line folding
     * routine, and ensure that long lines are chopped appropriately.
     */
    for (line = start = STR(buf); line; line = next_line) {
	next_line = split_at(line, '\n');
	len = next_line ? next_line - line - 1 : strlen(line);
	do {
	    if (len > var_line_limit) {
		output_text(context, REC_TYPE_CONT, line, var_line_limit, offset);
		line += var_line_limit;
		len -= var_line_limit;
		offset += var_line_limit;
	    } else {
		output_text(context, REC_TYPE_NORM, line, len, offset);
		offset += len;
		break;
	    }
	} while (len > 0);
	offset += 1;
    }
}
Beispiel #25
0
static inline karatsuba(num *a,num *b,num *c){
    /*
     *   a=[hi1:lo1]
     *   b=[h2:lo2]
     *   a=hi1*B^m2+lo1
     *   b=hi2*B^m2+lo2
     *   a*b=(hi1*hi2)B^(2*m2)+ (l1h2+l2h1) B^m2+lo1*lo2
     */
    if(a->n<2){
        mul1_(b,a->a[0],c);
        return;
    }
    if(b->n<2){
        mul1_(a,b->a[0],c);
        return;
    }
   /* printf("%d %d\n",a->n,b->n);
    printNum(a);
    printNum(b);
    printf("case #3\n");*/
    int m=max2(a->n,b->n);
    int m2=m/2;
    //printf("m2=%d\n",m2);
    num hi1,lo1,hi2,lo2,z0,z1,z2,t1,t2,lh1,lh2;
    split_at(a,m2,&hi1,&lo1);
    split_at(b,m2,&hi2,&lo2);
    /*puts("--- hi1 ---");
    printNum(&hi1);
    puts("--- lo1 ---");
    printNum(&lo1);
    puts("--- hi2 ---");
    printNum(&hi2);
    puts("--- lo2 ---");
    printNum(&lo2);
    */
    add_(&lo1,&hi1,&lh1);
    add_(&lo2,&hi2,&lh2);

    karatsuba(&lh1,&lh2,&z1);
    karatsuba(&lo1,&lo2,&z0);
    karatsuba(&hi1,&hi2,&z2);
    /*puts(" z0 z1 z2 ");
    printNum(&z0);
    printNum(&z1);
    printNum(&z2);
    */
    add_(&z0,&z2,&t1); //t1=z0+z2
    sub_(&z1,&t1,&t2);//t2=z1-t1
    //puts("t2= ");
    //printNum(&t2);
    shift_left(&z2,2*m2);//z2*B^2*m2
    shift_left(&t2,m2); //t2*B^m2
    //printNum(&z2);
    //printNum(&t2);
    //printNum(&z0);
    add_(&z0,&z2,c);
    //printNum(c);
    add_(c,&t2,c);
    rm0(c);
    //printNum(c);
}
Beispiel #26
0
VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why)
{
    const char *myname = "cidr_match_parse";
    char   *mask_search;
    char   *mask;
    MAI_HOSTADDR_STR hostaddr;
    unsigned char *np;
    unsigned char *mp;

    /*
     * Strip [] from [addr/len] or [addr]/len, destroying the pattern. CIDR
     * maps don't need [] to eliminate syntax ambiguity, but matchlists need
     * it. While stripping [], figure out where we should start looking for
     * /mask information.
     */
    if (*pattern == '[') {
	pattern++;
	if ((mask_search = split_at(pattern, ']')) == 0) {
	    vstring_sprintf(why ? why : (why = vstring_alloc(20)),
			    "missing ']' character after \"[%s\"", pattern);
	    return (why);
	} else if (*mask_search != '/') {
	    if (*mask_search != 0) {
		vstring_sprintf(why ? why : (why = vstring_alloc(20)),
				"garbage after \"[%s]\"", pattern);
		return (why);
	    }
	    mask_search = pattern;
	}
    } else
	mask_search = pattern;

    /*
     * Parse the pattern into network and mask, destroying the pattern.
     */
    if ((mask = split_at(mask_search, '/')) != 0) {
	ip->addr_family = CIDR_MATCH_ADDR_FAMILY(pattern);
	ip->addr_bit_count = CIDR_MATCH_ADDR_BIT_COUNT(ip->addr_family);
	ip->addr_byte_count = CIDR_MATCH_ADDR_BYTE_COUNT(ip->addr_family);
	if (!alldig(mask)
	    || (ip->mask_shift = atoi(mask)) > ip->addr_bit_count
	    || inet_pton(ip->addr_family, pattern, ip->net_bytes) != 1) {
	    vstring_sprintf(why ? why : (why = vstring_alloc(20)),
			  "bad net/mask pattern: \"%s/%s\"", pattern, mask);
	    return (why);
	}
	if (ip->mask_shift > 0) {
	    /* Allow for bytes > 8. */
	    memset(ip->mask_bytes, ~0U, ip->addr_byte_count);
	    mask_addr(ip->mask_bytes, ip->addr_byte_count, ip->mask_shift);
	} else
	    memset(ip->mask_bytes, 0, ip->addr_byte_count);

	/*
	 * Sanity check: all host address bits must be zero.
	 */
	for (np = ip->net_bytes, mp = ip->mask_bytes;
	     np < ip->net_bytes + ip->addr_byte_count; np++, mp++) {
	    if (*np & ~(*mp)) {
		mask_addr(ip->net_bytes, ip->addr_byte_count, ip->mask_shift);
		if (inet_ntop(ip->addr_family, ip->net_bytes, hostaddr.buf,
			      sizeof(hostaddr.buf)) == 0)
		    msg_fatal("inet_ntop: %m");
		vstring_sprintf(why ? why : (why = vstring_alloc(20)),
				"non-null host address bits in \"%s/%s\", "
				"perhaps you should use \"%s/%d\" instead",
				pattern, mask, hostaddr.buf, ip->mask_shift);
		return (why);
	    }
	}
    }

    /*
     * No /mask specified. Treat a bare network address as /allbits.
     */
    else {
	ip->addr_family = CIDR_MATCH_ADDR_FAMILY(pattern);
	ip->addr_bit_count = CIDR_MATCH_ADDR_BIT_COUNT(ip->addr_family);
	ip->addr_byte_count = CIDR_MATCH_ADDR_BYTE_COUNT(ip->addr_family);
	if (inet_pton(ip->addr_family, pattern, ip->net_bytes) != 1) {
	    vstring_sprintf(why ? why : (why = vstring_alloc(20)),
			    "bad address pattern: \"%s\"", pattern);
	    return (why);
	}
	ip->mask_shift = ip->addr_bit_count;
	/* Allow for bytes > 8. */
	memset(ip->mask_bytes, ~0U, ip->addr_byte_count);
    }

    /*
     * Wrap up the result.
     */
    ip->next = 0;

    return (0);
}
Beispiel #27
0
static void psc_dnsbl_add_site(const char *site)
{
    const char *myname = "psc_dnsbl_add_site";
    char   *saved_site = mystrdup(site);
    VSTRING *byte_codes = 0;
    PSC_DNSBL_HEAD *head;
    PSC_DNSBL_SITE *new_site;
    char    junk;
    const char *weight_text;
    char   *pattern_text;
    int     weight;
    HTABLE_INFO *ht;
    char   *parse_err;

    /*
     * Parse the required DNSBL domain name, the optional reply filter and
     * the optional reply weight factor.
     */
#define DO_GRIPE	1

    /* Negative weight means whitelist. */
    if ((weight_text = split_at(saved_site, '*')) != 0) {
	if (sscanf(weight_text, "%d%c", &weight, &junk) != 1)
	    msg_fatal("bad DNSBL weight factor \"%s\" in \"%s\"",
		      weight_text, site);
    } else {
	weight = 1;
    }
    /* Reply filter. */
    if ((pattern_text = split_at(saved_site, '=')) != 0) {
	byte_codes = vstring_alloc(100);
	if ((parse_err = ip_match_parse(byte_codes, pattern_text)) != 0)
	    msg_fatal("bad DNSBL filter syntax: %s", parse_err);
    }
    if (valid_hostname(saved_site, DO_GRIPE) == 0)
	msg_fatal("bad DNSBL domain name \"%s\" in \"%s\"",
		  saved_site, site);

    if (msg_verbose > 1)
	msg_info("%s: \"%s\" -> domain=\"%s\" pattern=\"%s\" weight=%d",
		 myname, site, saved_site, pattern_text ? pattern_text :
		 "null", weight);

    /*
     * Look up or create the (filter, weight) list head for this DNSBL domain
     * name.
     */
    if ((head = (PSC_DNSBL_HEAD *)
	 htable_find(dnsbl_site_cache, saved_site)) == 0) {
	head = (PSC_DNSBL_HEAD *) mymalloc(sizeof(*head));
	ht = htable_enter(dnsbl_site_cache, saved_site, (void *) head);
	/* Translate the DNSBL name into a safe name if available. */
	if (psc_dnsbl_reply == 0
	 || (head->safe_dnsbl = dict_get(psc_dnsbl_reply, saved_site)) == 0)
	    head->safe_dnsbl = ht->key;
	if (psc_dnsbl_reply && psc_dnsbl_reply->error)
	    msg_fatal("%s:%s lookup error", psc_dnsbl_reply->type,
		      psc_dnsbl_reply->name);
	head->first = 0;
    }

    /*
     * Append the new (filter, weight) node to the list for this DNSBL domain
     * name.
     */
    new_site = (PSC_DNSBL_SITE *) mymalloc(sizeof(*new_site));
    new_site->filter = (pattern_text ? mystrdup(pattern_text) : 0);
    new_site->byte_codes = (byte_codes ? ip_match_save(byte_codes) : 0);
    new_site->weight = weight;
    new_site->next = head->first;
    head->first = new_site;

    myfree(saved_site);
    if (byte_codes)
	vstring_free(byte_codes);
}
Beispiel #28
0
const char *smtpd_milter_eval(const char *name, void *ptr)
{
    SMTPD_STATE *state = (SMTPD_STATE *) ptr;
    const RESOLVE_REPLY *reply;
    char   *cp;

    /*
     * On-the-fly initialization.
     */
    if (state->expand_buf == 0)
	state->expand_buf = vstring_alloc(10);

    /*
     * Canonicalize the name.
     */
    if (*name != '{') {				/* } */
	vstring_sprintf(state->expand_buf, "{%s}", name);
	name = STR(state->expand_buf);
    }

    /*
     * System macros.
     */
    if (strcmp(name, S8_MAC_DAEMON_NAME) == 0)
	return (var_milt_daemon_name);
    if (strcmp(name, S8_MAC_V) == 0)
	return (var_milt_v);

    /*
     * Connect macros.
     */
    if (strcmp(name, S8_MAC__) == 0) {
	vstring_sprintf(state->expand_buf, "%s [%s]",
			state->reverse_name, state->addr);
	if (strcasecmp(state->name, state->reverse_name) != 0)
	    vstring_strcat(state->expand_buf, " (may be forged)");
	return (STR(state->expand_buf));
    }
    if (strcmp(name, S8_MAC_J) == 0)
	return (var_myhostname);
    if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
	return (state->rfc_addr);
    if (strcmp(name, S8_MAC_CLIENT_PORT) == 0)
	return (strcmp(state->port, CLIENT_PORT_UNKNOWN) ? state->port : "0");
    if (strcmp(name, S8_MAC_CLIENT_CONN) == 0) {
	vstring_sprintf(state->expand_buf, "%d", state->conn_count);
	return (STR(state->expand_buf));
    }
    if (strcmp(name, S8_MAC_CLIENT_NAME) == 0)
	return (state->name);
    if (strcmp(name, S8_MAC_CLIENT_PTR) == 0)
	return (state->reverse_name);
    if (strcmp(name, S8_MAC_CLIENT_RES) == 0)
	return (state->name_status == SMTPD_PEER_CODE_OK ? "OK" :
		state->name_status == SMTPD_PEER_CODE_FORGED ? "FORGED" :
	      state->name_status == SMTPD_PEER_CODE_TEMP ? "TEMP" : "FAIL");

    /*
     * HELO macros.
     */
#ifdef USE_TLS
#define IF_ENCRYPTED(x) (state->tls_context ? (x) : 0)
#define IF_TRUSTED(x) (TLS_CERT_IS_TRUSTED(state->tls_context) ? (x) : 0)

    if (strcmp(name, S8_MAC_TLS_VERSION) == 0)
	return (IF_ENCRYPTED(state->tls_context->protocol));
    if (strcmp(name, S8_MAC_CIPHER) == 0)
	return (IF_ENCRYPTED(state->tls_context->cipher_name));
    if (strcmp(name, S8_MAC_CIPHER_BITS) == 0) {
	if (state->tls_context == 0)
	    return (0);
	vstring_sprintf(state->expand_buf, "%d",
			IF_ENCRYPTED(state->tls_context->cipher_usebits));
	return (STR(state->expand_buf));
    }
    if (strcmp(name, S8_MAC_CERT_SUBJECT) == 0)
	return (IF_TRUSTED(state->tls_context->peer_CN));
    if (strcmp(name, S8_MAC_CERT_ISSUER) == 0)
	return (IF_TRUSTED(state->tls_context->issuer_CN));
#endif

    /*
     * MAIL FROM macros.
     */
#define IF_SASL_ENABLED(s) (smtpd_sasl_is_active(state) && (s) ? (s) : 0)

    if (strcmp(name, S8_MAC_I) == 0)
	return (state->queue_id);
#ifdef USE_SASL_AUTH
    if (strcmp(name, S8_MAC_AUTH_TYPE) == 0)
	return (IF_SASL_ENABLED(state->sasl_method));
    if (strcmp(name, S8_MAC_AUTH_AUTHEN) == 0)
	return (IF_SASL_ENABLED(state->sasl_username));
    if (strcmp(name, S8_MAC_AUTH_AUTHOR) == 0)
	return (IF_SASL_ENABLED(state->sasl_sender));
#endif
    if (strcmp(name, S8_MAC_MAIL_ADDR) == 0) {
	if (state->sender == 0)
	    return (0);
	if (state->sender[0] == 0)
	    return ("");
	reply = smtpd_resolve_addr(state->sender);
	/* Sendmail 8.13 does not externalize the null string. */
	if (STR(reply->recipient)[0])
	    quote_821_local(state->expand_buf, STR(reply->recipient));
	else
	    vstring_strcpy(state->expand_buf, STR(reply->recipient));
	return (STR(state->expand_buf));
    }
    if (strcmp(name, S8_MAC_MAIL_HOST) == 0) {
	if (state->sender == 0)
	    return (0);
	reply = smtpd_resolve_addr(state->sender);
	return (STR(reply->nexthop));
    }
    if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) {
	if (state->sender == 0)
	    return (0);
	reply = smtpd_resolve_addr(state->sender);
	return (STR(reply->transport));
    }

    /*
     * RCPT TO macros.
     */
    if (strcmp(name, S8_MAC_RCPT_ADDR) == 0) {
	if (state->recipient == 0)
	    return (0);
	if (state->recipient[0] == 0)
	    return ("");
	if (state->milter_reject_text) {
	    /* 554 5.7.1 <*****@*****.**>: Relay access denied */
	    vstring_strcpy(state->expand_buf, state->milter_reject_text + 4);
	    cp = split_at(STR(state->expand_buf), ' ');
	    return (cp ? split_at(cp, ' ') : cp);
	}
	reply = smtpd_resolve_addr(state->recipient);
	/* Sendmail 8.13 does not externalize the null string. */
	if (STR(reply->recipient)[0])
	    quote_821_local(state->expand_buf, STR(reply->recipient));
	else
	    vstring_strcpy(state->expand_buf, STR(reply->recipient));
	return (STR(state->expand_buf));
    }
    if (strcmp(name, S8_MAC_RCPT_HOST) == 0) {
	if (state->recipient == 0)
	    return (0);
	if (state->milter_reject_text) {
	    /* 554 5.7.1 <*****@*****.**>: Relay access denied */
	    vstring_strcpy(state->expand_buf, state->milter_reject_text + 4);
	    (void) split_at(STR(state->expand_buf), ' ');
	    return (STR(state->expand_buf));
	}
	reply = smtpd_resolve_addr(state->recipient);
	return (STR(reply->nexthop));
    }
    if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) {
	if (state->recipient == 0)
	    return (0);
	if (state->milter_reject_text)
	    return (S8_RCPT_MAILER_ERROR);
	reply = smtpd_resolve_addr(state->recipient);
	return (STR(reply->transport));
    }
    return (0);
}
Beispiel #29
0
void    smtpd_peer_init(SMTPD_STATE *state)
{
    const char *myname = "smtpd_peer_init";
    SOCKADDR_SIZE sa_length;
    struct sockaddr *sa;
    INET_PROTO_INFO *proto_info = inet_proto_info();

    sa = (struct sockaddr *) & (state->sockaddr);
    sa_length = sizeof(state->sockaddr);

    /*
     * Look up the peer address information.
     * 
     * XXX If we make local endpoint (getsockname) information available to
     * Milter applications as {if_name} and {if_addr}, then we also must be
     * able to provide this via the XCLIENT command for Milter testing.
     * 
     * XXX If we make local or remote port information available to policy
     * servers or Milter applications, then we must also make this testable
     * with the XCLIENT command, otherwise there will be confusion.
     * 
     * XXX If we make local or remote port information available via logging,
     * then we must also support these attributes with the XFORWARD command.
     * 
     * XXX If support were to be added for Milter applications in down-stream
     * MTAs, then consistency demands that we propagate a lot of Sendmail
     * macro information via the XFORWARD command. Otherwise we could end up
     * with a very confusing situation.
     */
    if (getpeername(vstream_fileno(state->client), sa, &sa_length) >= 0) {
	errno = 0;
    }

    /*
     * If peer went away, give up.
     */
    if (errno != 0 && errno != ENOTSOCK) {
	state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
	state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
	state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
	state->addr_family = AF_UNSPEC;
	state->name_status = SMTPD_PEER_CODE_PERM;
	state->reverse_name_status = SMTPD_PEER_CODE_PERM;
	state->port = mystrdup(CLIENT_PORT_UNKNOWN);
    }

    /*
     * Convert the client address to printable address and hostname.
     * 
     * XXX If we're given an IPv6 (or IPv4) connection from, e.g., inetd, while
     * Postfix IPv6 (or IPv4) support is turned off, don't (skip to the final
     * else clause, pretend the origin is localhost[127.0.0.1], and become an
     * open relay).
     */
    else if (errno == 0
	     && (sa->sa_family == AF_INET
#ifdef AF_INET6
		 || sa->sa_family == AF_INET6
#endif
		 )) {
	MAI_HOSTNAME_STR client_name;
	MAI_HOSTADDR_STR client_addr;
	MAI_SERVPORT_STR client_port;
	int     aierr;
	char   *colonp;

	/*
	 * Sanity check: we can't use sockets that we're not configured for.
	 */
	if (strchr((char *) proto_info->sa_family_list, sa->sa_family) == 0)
	    msg_fatal("cannot handle socket type %s with \"%s = %s\"",
#ifdef AF_INET6
		      sa->sa_family == AF_INET6 ? "AF_INET6" :
#endif
		      sa->sa_family == AF_INET ? "AF_INET" :
		      "other", VAR_INET_PROTOCOLS, var_inet_protocols);

	/*
	 * Sorry, but there are some things that we just cannot do while
	 * connected to the network.
	 */
	if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
	    msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
		      (unsigned long) getuid(), (unsigned long) geteuid());
	    msg_fatal("the Postfix SMTP server must run with $%s privileges",
		      VAR_MAIL_OWNER);
	}

	/*
	 * Convert the client address to printable form.
	 */
	if ((aierr = sockaddr_to_hostaddr(sa, sa_length, &client_addr,
					  &client_port, 0)) != 0)
	    msg_fatal("%s: cannot convert client address/port to string: %s",
		      myname, MAI_STRERROR(aierr));
	state->port = mystrdup(client_port.buf);

	/*
	 * XXX Strip off the IPv6 datalink suffix to avoid false alarms with
	 * strict address syntax checks.
	 */
#ifdef HAS_IPV6
	(void) split_at(client_addr.buf, '%');
#endif

	/*
	 * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
	 * but only if IPv4 support is enabled (why would anyone want to turn
	 * it off)? With IPv4 support enabled we have no need for the IPv6
	 * form in logging, hostname verification and access checks.
	 */
#ifdef HAS_IPV6
	if (sa->sa_family == AF_INET6) {
	    if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
		&& IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
		&& (colonp = strrchr(client_addr.buf, ':')) != 0) {
		struct addrinfo *res0;

		if (msg_verbose > 1)
		    msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
			     myname, client_addr.buf, colonp + 1);

		state->addr = mystrdup(colonp + 1);
		state->rfc_addr = mystrdup(colonp + 1);
		state->addr_family = AF_INET;
		aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
		if (aierr)
		    msg_fatal("%s: cannot convert %s from string to binary: %s",
			      myname, state->addr, MAI_STRERROR(aierr));
		sa_length = res0->ai_addrlen;
		if (sa_length > sizeof(state->sockaddr))
		    sa_length = sizeof(state->sockaddr);
		memcpy((char *) sa, res0->ai_addr, sa_length);
		freeaddrinfo(res0);		/* 200412 */
	    }

	    /*
	     * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
	     * a prefix of 'IPv6:'. We do this consistently for all IPv6
	     * addresses that that appear in headers or envelopes. The fact
	     * that valid_mailhost_addr() enforces the form helps of course.
	     * We use the form without IPV6: prefix when doing access
	     * control, or when accessing the connection cache.
	     */
	    else {
		state->addr = mystrdup(client_addr.buf);
		state->rfc_addr =
		    concatenate(IPV6_COL, client_addr.buf, (char *) 0);
		state->addr_family = sa->sa_family;
	    }
	}

	/*
	 * An IPv4 address is in dotted quad decimal form.
	 */
	else
#endif
	{
	    state->addr = mystrdup(client_addr.buf);
	    state->rfc_addr = mystrdup(client_addr.buf);
	    state->addr_family = sa->sa_family;
	}

	/*
	 * Look up and sanity check the client hostname.
	 * 
	 * It is unsafe to allow numeric hostnames, especially because there
	 * exists pressure to turn off the name->addr double check. In that
	 * case an attacker could trivally bypass access restrictions.
	 * 
	 * sockaddr_to_hostname() already rejects malformed or numeric names.
	 */
#define TEMP_AI_ERROR(e) \
	((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)

#define REJECT_PEER_NAME(state, code) { \
	myfree(state->name); \
	state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
	state->name_status = code; \
    }

	if (var_smtpd_peername_lookup == 0) {
	    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->name_status = SMTPD_PEER_CODE_PERM;
	    state->reverse_name_status = SMTPD_PEER_CODE_PERM;
	} else if ((aierr = sockaddr_to_hostname(sa, sa_length, &client_name,
					 (MAI_SERVNAME_STR *) 0, 0)) != 0) {
	    state->name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->reverse_name = mystrdup(CLIENT_NAME_UNKNOWN);
	    state->name_status = (TEMP_AI_ERROR(aierr) ?
			       SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
	    state->reverse_name_status = (TEMP_AI_ERROR(aierr) ?
			       SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
	} else {
	    struct addrinfo *res0;
	    struct addrinfo *res;

	    state->name = mystrdup(client_name.buf);
	    state->reverse_name = mystrdup(client_name.buf);
	    state->name_status = SMTPD_PEER_CODE_OK;
	    state->reverse_name_status = SMTPD_PEER_CODE_OK;

	    /*
	     * Reject the hostname if it does not list the peer address.
	     * Without further validation or qualification, such information
	     * must not be allowed to enter the audit trail, as people would
	     * draw false conclusions.
	     */
	    aierr = hostname_to_sockaddr_pf(state->name, state->addr_family,
					    (char *) 0, 0, &res0);
	    if (aierr) {
		msg_warn("%s: hostname %s verification failed: %s",
			 state->addr, state->name, MAI_STRERROR(aierr));
		REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
			    SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_FORGED));
	    } else {
		for (res = res0; /* void */ ; res = res->ai_next) {
		    if (res == 0) {
			msg_warn("%s: address not listed for hostname %s",
				 state->addr, state->name);
			REJECT_PEER_NAME(state, SMTPD_PEER_CODE_FORGED);
			break;
		    }
		    if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
			msg_info("skipping address family %d for host %s",
				 res->ai_family, state->name);
			continue;
		    }
		    if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
			break;			/* keep peer name */
		}
		freeaddrinfo(res0);
	    }
	}
    }

    /*
     * If it's not Internet, assume the client is local, and avoid using the
     * naming service because that can hang when the machine is disconnected.
     */
    else {
	state->name = mystrdup("localhost");
	state->reverse_name = mystrdup("localhost");
	state->addr = mystrdup("127.0.0.1");	/* XXX bogus. */
	state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
	state->addr_family = AF_UNSPEC;
	state->name_status = SMTPD_PEER_CODE_OK;
	state->reverse_name_status = SMTPD_PEER_CODE_OK;
	state->port = mystrdup("0");		/* XXX bogus. */
    }

    /*
     * Do the name[addr]:port formatting for pretty reports.
     */
    state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr,
					     state->port);
}
Beispiel #30
0
static void get_service_attr(SPAWN_ATTR *attr, char *service, char **argv)
{
    const char *myname = "get_service_attr";
    struct passwd *pwd;
    struct group *grp;
    char   *user;			/* user name */
    char   *group;			/* group name */

    /*
     * Initialize.
     */
    user = 0;
    group = 0;
    attr->argv = 0;

    /*
     * Figure out the command time limit for this transport.
     */
    attr->time_limit =
	get_mail_conf_time2(service, _MAXTIME, var_command_maxtime, 's', 1, 0);

    /*
     * Iterate over the command-line attribute list.
     */
    for ( /* void */ ; *argv != 0; argv++) {

	/*
	 * user=username[:groupname]
	 */
	if (strncasecmp("user="******"user="******"user="******"unknown user name: %s", user);
	    attr->uid = pwd->pw_uid;
	    if (group != 0) {
		if ((grp = getgrnam(group)) == 0)
		    msg_fatal("unknown group name: %s", group);
		attr->gid = grp->gr_gid;
	    } else {
		attr->gid = pwd->pw_gid;
	    }
	}

	/*
	 * argv=command...
	 */
	else if (strncasecmp("argv=", *argv, sizeof("argv=") - 1) == 0) {
	    *argv += sizeof("argv=") - 1;	/* XXX clobbers argv */
	    attr->argv = argv;
	    break;
	}

	/*
	 * Bad.
	 */
	else
	    msg_fatal("unknown attribute name: %s", *argv);
    }

    /*
     * Sanity checks. Verify that every member has an acceptable value.
     */
    if (user == 0)
	msg_fatal("missing user= attribute");
    if (attr->argv == 0)
	msg_fatal("missing argv= attribute");
    if (attr->uid == 0)
	msg_fatal("request to deliver as root");
    if (attr->uid == var_owner_uid)
	msg_fatal("request to deliver as mail system owner");
    if (attr->gid == 0)
	msg_fatal("request to use privileged group id %ld", (long) attr->gid);
    if (attr->gid == var_owner_gid)
	msg_fatal("request to use mail system owner group id %ld", (long) attr->gid);
    if (attr->uid == (uid_t) (-1))
	msg_fatal("user must not have user ID -1");
    if (attr->gid == (gid_t) (-1))
	msg_fatal("user must not have group ID -1");

    /*
     * Give the poor tester a clue of what is going on.
     */
    if (msg_verbose)
	msg_info("%s: uid %ld, gid %ld; time %d",
	      myname, (long) attr->uid, (long) attr->gid, attr->time_limit);
}