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); }
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)); }
int valid_hostname(const char *name, int gripe) { const char *myname = "valid_hostname"; const char *cp; int label_length = 0; int label_count = 0; int non_numeric = 0; int ch; /* * Trivial cases first. */ if (*name == 0) { if (gripe) msg_warn("%s: empty hostname", myname); return (0); } /* * Find bad characters or label lengths. Find adjacent delimiters. */ for (cp = name; (ch = *(unsigned char *) cp) != 0; cp++) { if (ISALNUM(ch) || ch == '_') { /* grr.. */ if (label_length == 0) label_count++; label_length++; if (label_length > VALID_LABEL_LEN) { if (gripe) msg_warn("%s: hostname label too long: %.100s", myname, name); return (0); } if (!ISDIGIT(ch)) non_numeric = 1; } else if (ch == '.') { if (label_length == 0 || cp[1] == 0) { if (gripe) msg_warn("%s: misplaced delimiter: %.100s", myname, name); return (0); } label_length = 0; } else if (ch == '-') { non_numeric = 1; label_length++; if (label_length == 1 || cp[1] == 0 || cp[1] == '.') { if (gripe) msg_warn("%s: misplaced hyphen: %.100s", myname, name); return (0); } } #ifdef SLOPPY_VALID_HOSTNAME else if (ch == ':' && valid_ipv6_hostaddr(name, DONT_GRIPE)) { non_numeric = 0; break; } #endif else { if (gripe) msg_warn("%s: invalid character %d(decimal): %.100s", myname, ch, name); return (0); } } if (non_numeric == 0) { if (gripe) msg_warn("%s: numeric hostname: %.100s", myname, name); #ifndef SLOPPY_VALID_HOSTNAME return (0); #endif } if (cp - name > VALID_HOSTNAME_LEN) { if (gripe) msg_warn("%s: bad length %d for %.100s...", myname, (int) (cp - name), name); return (0); } return (1); }