out.c.patch   [plain text]


--- /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;
     }