--- /tmp/jabberd-2.2.14/s2s/out.c 2011-05-31 15:11:37.000000000 -0700 +++ ./jabberd2/s2s/out.c 2011-07-25 00:14:20.000000000 -0700 @@ -391,7 +391,7 @@ int out_route(s2s_t s2s, char *route, in char ipport[INET6_ADDRSTRLEN + 16], *dkey, *c; time_t now; int reuse = 0; - char ip[INET6_ADDRSTRLEN]; + char ip[INET6_ADDRSTRLEN] = {0}; int port, c_len, from_len; c = memchr(route, '/', routelen); @@ -513,7 +513,19 @@ int out_route(s2s_t s2s, char *route, in /* connect */ log_debug(ZONE, "initiating connection to %s", ipport); - (*out)->fd = mio_connect(s2s->mio, port, ip, s2s->origin_ip, _out_mio_callback, (void *) *out); + /* APPLE: multiple origin_ips may be specified; use IPv6 if possible or otherwise IPv4 */ + int ip_is_v6 = 0; + if (strchr(ip, ':') != NULL) + ip_is_v6 = 1; + int i; + for (i = 0; i < s2s->origin_nips; i++) { + // only bother with mio_connect if the src and dst IPs are of the same type + if ((ip_is_v6 && (strchr(s2s->origin_ips[i], ':') != NULL)) || // both are IPv6 + (! ip_is_v6 && (strchr(s2s->origin_ips[i], ':') == NULL))) // both are IPv4 + (*out)->fd = mio_connect(s2s->mio, port, ip, s2s->origin_ips[i], _out_mio_callback, (void *) *out); + + if ((*out)->fd != NULL) break; + } if ((*out)->fd == NULL) { dnsres_t bad; @@ -596,6 +608,22 @@ int out_packet(s2s_t s2s, pkt_t pkt) { conn_state_t state; int ret; + /* perform check against whitelist */ + if (s2s->enable_whitelist > 0 && + (pkt->to->domain != NULL) && + (s2s_domain_in_whitelist(s2s, pkt->to->domain) == 0)) { + log_write(s2s->log, LOG_NOTICE, "sending a packet to domain not in the whitelist, dropping it"); + if (pkt->to != NULL) + jid_free(pkt->to); + if (pkt->from != NULL) + jid_free(pkt->from); + if (pkt->nad != NULL) + nad_free(pkt->nad); + free(pkt); + + return; + } + /* new route key */ rkey = s2s_route_key(NULL, pkt->from->domain, pkt->to->domain); rkeylen = strlen(rkey); @@ -683,8 +711,9 @@ int out_packet(s2s_t s2s, pkt_t pkt) { } /* this is a new route - send dialback auth request to piggyback on the existing connection */ + if (out->s2s->require_tls == 0 || out->s->ssf > 0) { _out_dialback(out, rkey, rkeylen); - + } free(rkey); return 0; } @@ -1541,7 +1570,7 @@ static int _out_sx_callback(sx_t s, sx_e /* if no stream version from either side, kick off dialback for each route, */ /* otherwise wait for stream features */ - if ((out->s->res_version==NULL) || (out->s2s->sx_ssl == NULL)) { + if (((out->s->res_version==NULL) || (out->s2s->sx_ssl == NULL)) && out->s2s->require_tls == 0) { log_debug(ZONE, "no stream version, sending dialbacks for %s immediately", out->key); out->online = 1; send_dialbacks(out); @@ -1573,7 +1602,7 @@ static int _out_sx_callback(sx_t s, sx_e elem = nad_find_elem(nad, 0, ns, "starttls", 1); if(elem >= 0) { log_debug(ZONE, "got STARTTLS in stream features"); - if(sx_ssl_client_starttls(out->s2s->sx_ssl, s, out->s2s->local_pemfile) == 0) { + if(sx_ssl_client_starttls(out->s2s->sx_ssl, s, out->s2s->local_pemfile, out->s2s->local_private_key_password) == 0) { starttls = 1; nad_free(nad); return 0; @@ -1585,13 +1614,19 @@ static int _out_sx_callback(sx_t s, sx_e /* If we're not establishing a starttls connection, send dialbacks */ if (!starttls) { + if (out->s2s->require_tls == 0 || s->ssf > 0) { log_debug(ZONE, "No STARTTLS, sending dialbacks for %s", out->key); out->online = 1; send_dialbacks(out); + } else { + log_debug(ZONE, "No STARTTLS, dialbacks disabled for non-TLS connections, cannot complete negotiation"); + } } #else + if (out->s2s->require_tls == 0) { out->online = 1; send_dialbacks(out); + } #endif } @@ -1622,7 +1657,10 @@ static int _out_sx_callback(sx_t s, sx_e return 0; case event_CLOSED: + if (out->fd != NULL) { mio_close(out->s2s->mio, out->fd); + out->fd = NULL; + } return -1; }