Пример #1
0
int     valid_mailhost_literal(const char *addr, int gripe)
{
    const char *myname = "valid_mailhost_literal";
    MAI_HOSTADDR_STR hostaddr;
    const char *last;
    size_t address_bytes;

    if (*addr != '[') {
	if (gripe)
	    msg_warn("%s: '[' expected at start: %.100s", myname, addr);
	return (0);
    }
    if ((last = strchr(addr, ']')) == 0) {
	if (gripe)
	    msg_warn("%s: ']' expected at end: %.100s", myname, addr);
	return (0);
    }
    if (last[1]) {
	if (gripe)
	    msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
	return (0);
    }
    if ((address_bytes = last - addr - 1) >= sizeof(hostaddr.buf)) {
	if (gripe)
	    msg_warn("%s: too much text: %.100s", myname, addr);
	return (0);
    }
    strncpy(hostaddr.buf, addr + 1, address_bytes);
    hostaddr.buf[address_bytes] = 0;
    return (valid_mailhost_addr(hostaddr.buf, gripe) != 0);
}
Пример #2
0
int     main(int unused_argc, char **argv)
{
    VSTRING *buffer = vstring_alloc(1);

    msg_vstream_init(argv[0], VSTREAM_ERR);
    msg_verbose = 1;

    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
	msg_info("testing: \"%s\"", vstring_str(buffer));
	if (vstring_str(buffer)[0] == '[')
	    valid_mailhost_literal(vstring_str(buffer), DO_GRIPE);
	else
	    valid_mailhost_addr(vstring_str(buffer), DO_GRIPE);
    }
    exit(0);
}
Пример #3
0
int     resolve_local(const char *addr)
{
    char   *saved_addr = mystrdup(addr);
    char   *dest;
    const char *bare_dest;
    struct addrinfo *res0 = 0;
    ssize_t len;

    /*
     * The optimizer will eliminate tests that always fail.
     */
#define RETURN(x) \
    do { \
	myfree(saved_addr); \
	if (res0) \
	    freeaddrinfo(res0); \
	return(x); \
    } while (0)

    if (resolve_local_list == 0)
	resolve_local_init();

    /*
     * Strip one trailing dot but not dot-dot.
     * 
     * XXX This should not be distributed all over the code. Problem is,
     * addresses can enter the system via multiple paths: networks, local
     * forward/alias/include files, even as the result of address rewriting.
     */
    len = strlen(saved_addr);
    if (len == 0)
	RETURN(0);
    if (saved_addr[len - 1] == '.')
	saved_addr[--len] = 0;
    if (len == 0 || saved_addr[len - 1] == '.')
	RETURN(0);

    /*
     * Compare the destination against the list of destinations that we
     * consider local.
     */
    if (string_list_match(resolve_local_list, saved_addr))
	RETURN(1);
    if (resolve_local_list->error != 0)
	RETURN(resolve_local_list->error);

    /*
     * Compare the destination against the list of interface addresses that
     * we are supposed to listen on.
     * 
     * The destination may be an IPv6 address literal that was buried somewhere
     * inside a deeply recursively nested address. This information comes
     * from an untrusted source, and Wietse is not confident that everyone's
     * getaddrinfo() etc. implementation is sufficiently robust. The syntax
     * is complex enough with null field compression and with IPv4-in-IPv6
     * addresses that errors are likely.
     * 
     * The solution below is ad-hoc. We neutralize the string as soon as we
     * realize that its contents could be harmful. We neutralize the string
     * here, instead of neutralizing it in every resolve_local() caller.
     * That's because resolve_local knows how the address is going to be
     * parsed and converted into binary form.
     * 
     * There are several more structural solutions to this.
     * 
     * - One solution is to disallow address literals. This is not as bad as it
     * seems: I have never seen actual legitimate use of address literals.
     * 
     * - Another solution is to label each string with a trustworthiness label
     * and to expect that all Postfix infrastructure will exercise additional
     * caution when given a string with untrusted content. This is not likely
     * to happen.
     * 
     * FIX 200501 IPv6 patch did not require "IPv6:" prefix in numerical
     * addresses.
     */
    dest = saved_addr;
    if (*dest == '[' && dest[len - 1] == ']') {
	dest++;
	dest[len -= 2] = 0;
	if ((bare_dest = valid_mailhost_addr(dest, DO_GRIPE)) != 0
	    && hostaddr_to_sockaddr(bare_dest, (char *) 0, 0, &res0) == 0) {
	    if (own_inet_addr(res0->ai_addr) || proxy_inet_addr(res0->ai_addr))
		RETURN(1);
	}
    }

    /*
     * Must be remote, or a syntax error.
     */
    RETURN(0);
}