Ejemplo n.º 1
0
static void smtpd_peer_from_pass_attr(SMTPD_STATE *state)
{
    HTABLE *attr = (HTABLE *) vstream_context(state->client);
    const char *cp;

    /*
     * Extract the client endpoint information from the attribute hash.
     */
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0)
	msg_fatal("missing client address from proxy");
    if (strrchr(cp, ':') != 0) {
	if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0)
	    msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
	state->addr = mystrdup(cp);
	state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0);
	state->addr_family = AF_INET6;
    } else {
	if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0)
	    msg_fatal("bad IPv4 client address syntax from proxy: %s", cp);
	state->addr = mystrdup(cp);
	state->rfc_addr = mystrdup(cp);
	state->addr_family = AF_INET;
    }
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0)
	msg_fatal("missing client port from proxy");
    if (valid_hostport(cp, DO_GRIPE) == 0)
	msg_fatal("bad TCP client port number syntax from proxy: %s", cp);
    state->port = mystrdup(cp);

    /*
     * The Dovecot authentication server needs the server IP address.
     */
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0)
	msg_fatal("missing server address from proxy");
    if (valid_hostaddr(cp, DO_GRIPE) == 0)
	msg_fatal("bad IPv6 server address syntax from proxy: %s", cp);
    state->dest_addr = mystrdup(cp);

    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_PORT)) == 0)
	msg_fatal("missing server port from proxy");
    if (valid_hostport(cp, DO_GRIPE) == 0)
	msg_fatal("bad TCP server port number syntax from proxy: %s", cp);
    state->dest_port = mystrdup(cp);

    /*
     * Convert the client address from string to binary form.
     */
    smtpd_peer_hostaddr_to_sockaddr(state);
}
Ejemplo n.º 2
0
int     valid_hostaddr(const char *addr, int gripe)
{
    const char *myname = "valid_hostaddr";

    /*
     * Trivial cases first.
     */
    if (*addr == 0) {
	if (gripe)
	    msg_warn("%s: empty address", myname);
	return (0);
    }

    /*
     * Protocol-dependent processing next.
     */
    if (strchr(addr, ':') != 0)
	return (valid_ipv6_hostaddr(addr, gripe));
    else
	return (valid_ipv4_hostaddr(addr, gripe));
}
Ejemplo n.º 3
0
int     valid_ipv6_hostaddr(const char *addr, int gripe)
{
    const char *myname = "valid_ipv6_hostaddr";
    int     null_field = 0;
    int     field = 0;
    unsigned char *cp = (unsigned char *) addr;
    int     len = 0;

    /*
     * FIX 200501 The IPv6 patch validated syntax with getaddrinfo(), but I
     * am not confident that everyone's system library routines are robust
     * enough, like buffer overflow free. Remember, the valid_hostmumble()
     * routines are meant to protect Postfix against malformed information in
     * data received from the network.
     * 
     * We require eight-field hex addresses of the form 0:1:2:3:4:5:6:7,
     * 0:1:2:3:4:5:6a.6b.7c.7d, or some :: compressed version of the same.
     * 
     * Note: the character position is advanced inside the loop. I have added
     * comments to show why we can't get stuck.
     */
    for (;;) {
	switch (*cp) {
	case 0:
	    /* Terminate the loop. */
	    if (field < 2) {
		if (gripe)
		    msg_warn("%s: too few `:' in IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    } else if (len == 0 && null_field != field - 1) {
		if (gripe)
		    msg_warn("%s: bad null last field in IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    } else
		return (1);
	case '.':
	    /* Terminate the loop. */
	    if (field < 2 || field > 6) {
		if (gripe)
		    msg_warn("%s: malformed IPv4-in-IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    } else
		/* NOT: valid_hostaddr(). Avoid recursion. */
		return (valid_ipv4_hostaddr((char *) cp - len, gripe));
	case ':':
	    /* Advance by exactly 1 character position or terminate. */
	    if (field == 0 && len == 0 && ISALNUM(cp[1])) {
		if (gripe)
		    msg_warn("%s: bad null first field in IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    }
	    field++;
	    if (field > 7) {
		if (gripe)
		    msg_warn("%s: too many `:' in IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    }
	    cp++;
	    len = 0;
	    if (*cp == ':') {
		if (null_field > 0) {
		    if (gripe)
			msg_warn("%s: too many `::' in IPv6 address: %.100s",
				 myname, addr);
		    return (0);
		}
		null_field = field;
	    }
	    break;
	default:
	    /* Advance by at least 1 character position or terminate. */
	    len = strspn((char *) cp, "0123456789abcdefABCDEF");
	    if (len /* - strspn((char *) cp, "0") */ > 4) {
		if (gripe)
		    msg_warn("%s: malformed IPv6 address: %.100s",
			     myname, addr);
		return (0);
	    }
	    if (len <= 0) {
		if (gripe)
		    msg_warn("%s: invalid character %d(decimal) in IPv6 address: %.100s",
			     myname, *cp, addr);
		return (0);
	    }
	    cp += len;
	    break;
	}
    }
}