*** s2s/s2s.h.orig Thu Apr 15 04:26:04 2004 --- s2s/s2s.h Fri Oct 29 14:54:47 2004 *************** *** 95,100 **** --- 95,103 ---- /** dialback secret */ char *local_secret; + /** pemfile for peer connections */ + char *local_pemfile; + /** time checks */ int check_interval; int check_queue; *** s2s/main.c.orig Tue Oct 12 08:42:34 2004 --- s2s/main.c Fri Oct 29 15:16:48 2004 *************** *** 134,139 **** --- 134,143 ---- if(s2s->local_secret == NULL) s2s->local_secret = "secret"; + s2s->local_pemfile = config_get_one(s2s->config, "local.pemfile", 0); + if (s2s->local_pemfile != NULL) + log_debug(ZONE,"loaded local pemfile for peer s2s connections"); + s2s->check_interval = j_atoi(config_get_one(s2s->config, "check.interval", 0), 0); s2s->check_queue = j_atoi(config_get_one(s2s->config, "check.queue", 0), 0); s2s->check_invalid = j_atoi(config_get_one(s2s->config, "check.invalid", 0), 0); *************** *** 174,186 **** --- 178,194 ---- do { xhash_iter_get(s2s->outq, (const char **) &domain, (void **) &q); + log_debug(ZONE, "running time checks for %s", domain); + /* dns lookup timeout check first */ dns = xhash_get(s2s->dnscache, domain); if(dns == NULL) continue; if(dns->pending) { + log_debug(ZONE, "dns lookup pending for %s", domain); if(now > dns->init_time + s2s->check_queue) { + log_debug(ZONE, "dns lookup expired for %s, bouncing packets in queue", domain); /* bounce queue */ while((pkt = jqueue_pull(q)) != NULL) { if(pkt->nad->ecur > 1 && NAD_NURI_L(pkt->nad, NAD_ENS(pkt->nad, 1)) == strlen(uri_CLIENT) && strncmp(NAD_NURI(pkt->nad, NAD_ENS(pkt->nad, 1)), uri_CLIENT, strlen(uri_CLIENT)) == 0) *************** *** 208,213 **** --- 216,223 ---- conn = xhash_get(s2s->out, ipport); if(conn == NULL) { /* no pending conn? perhaps it failed? */ + log_debug(ZONE, "no pending connection for %s, bouncing queue", domain); + /* bounce queue */ while((pkt = jqueue_pull(q)) != NULL) { if(pkt->nad->ecur > 1 && NAD_NURI_L(pkt->nad, NAD_ENS(pkt->nad, 1)) == strlen(uri_CLIENT) && strncmp(NAD_NURI(pkt->nad, NAD_ENS(pkt->nad, 1)), uri_CLIENT, strlen(uri_CLIENT)) == 0) *************** *** 225,230 **** --- 235,241 ---- /* connect timeout check */ if(!conn->online && now > conn->init_time + s2s->check_queue) { + log_debug(ZONE, "connection to %s is not online yet, bouncing queue", domain); /* !!! kill conn if necessary */ /* bounce queue */ while((pkt = jqueue_pull(q)) != NULL) { *************** *** 246,258 **** if(xhash_iter_first(s2s->out)) do { xhash_iter_get(s2s->out, (const char **) &key, (void *) &conn); if(xhash_iter_first(conn->states)) do { xhash_iter_get(conn->states, NULL, (void *) &state); /* drop invalid */ ! if(state == conn_INVALID) xhash_zap(conn->states, key); } while(xhash_iter_next(conn->states)); } while(xhash_iter_next(s2s->out)); --- 257,272 ---- if(xhash_iter_first(s2s->out)) do { xhash_iter_get(s2s->out, (const char **) &key, (void *) &conn); + log_debug(ZONE, "checking connection state for %s", key); if(xhash_iter_first(conn->states)) do { xhash_iter_get(conn->states, NULL, (void *) &state); /* drop invalid */ ! if(state == conn_INVALID) { xhash_zap(conn->states, key); + log_debug(ZONE, "dropping invalid connection for conn key %s", key); + } } while(xhash_iter_next(conn->states)); } while(xhash_iter_next(s2s->out)); *************** *** 379,385 **** s2s->sx_env = sx_env_new(); #ifdef HAVE_SSL ! /* get ssl online, so we can encrypt to the router */ if(s2s->sx_ssl == NULL && s2s->router_pemfile != NULL) { s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, s2s->router_pemfile, NULL); if(s2s->sx_ssl == NULL) { --- 393,409 ---- s2s->sx_env = sx_env_new(); #ifdef HAVE_SSL ! /* get the ssl context up and running */ ! if(s2s->local_pemfile != NULL) { ! s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, s2s->local_pemfile); ! if(s2s->sx_ssl == NULL) { ! log_write(s2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to peers"); ! s2s->local_pemfile = NULL; ! } else ! log_debug(ZONE, "loaded pemfile for SSL connections to peers"); ! } ! ! /* try and get something online, so at least we can encrypt to the router */ if(s2s->sx_ssl == NULL && s2s->router_pemfile != NULL) { s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, s2s->router_pemfile, NULL); if(s2s->sx_ssl == NULL) { *** s2s/in.c.orig Wed Mar 24 04:25:23 2004 --- s2s/in.c Fri Oct 29 16:14:56 2004 *************** *** 86,91 **** --- 86,92 ---- log_debug(ZONE, "close action on fd %d", fd); /* !!! logging */ + log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect", fd, in->ip, in->port); jqueue_push(in->s2s->dead, (void *) in->s, 0); *************** *** 107,113 **** getpeername(fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); ! log_write(s2s->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port); /* new conn */ in = (conn_t) malloc(sizeof(struct conn_st)); --- 108,114 ---- getpeername(fd, (struct sockaddr *) &sa, &namelen); port = j_inet_getport(&sa); ! log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd, (char *) data, port); /* new conn */ in = (conn_t) malloc(sizeof(struct conn_st)); *************** *** 127,134 **** in->s = sx_new(s2s->sx_env, in->fd, _in_sx_callback, (void *) in); mio_app(m, in->fd, in_mio_callback, (void *) in); sx_server_init(in->s, S2S_DB_HEADER); ! break; } --- 128,138 ---- in->s = sx_new(s2s->sx_env, in->fd, _in_sx_callback, (void *) in); mio_app(m, in->fd, in_mio_callback, (void *) in); + #ifdef HAVE_SSL + sx_server_init(in->s, S2S_DB_HEADER | ((s2s->local_pemfile != NULL) ? SX_SSL_STARTTLS_OFFER : 0) ); + #else sx_server_init(in->s, S2S_DB_HEADER); ! #endif break; } *************** *** 212,229 **** case event_STREAM: case event_OPEN: /* first time, bring them online */ ! if(!in->online) { log_debug(ZONE, "incoming conn from %s port %d is online (id %s)", in->ip, in->port, s->id); in->online = 1; /* record the id */ in->key = strdup(s->id); /* track it */ xhash_put(in->s2s->in, in->key, (void *) in); ! } break; --- 216,237 ---- case event_STREAM: case event_OPEN: + log_debug(ZONE, "STREAM or OPEN event from %s port %d (id %s)", in->ip, in->port, s->id); + /* first time, bring them online */ ! if ((!in->online)||(strcmp(in->key,s->id)!=0)) { log_debug(ZONE, "incoming conn from %s port %d is online (id %s)", in->ip, in->port, s->id); in->online = 1; /* record the id */ + if (in->key != NULL) + log_debug(ZONE,"adding new SSL stream id %s for stream id %s", s->id, in->key); in->key = strdup(s->id); /* track it */ xhash_put(in->s2s->in, in->key, (void *) in); ! } break; *** s2s/out.c.orig Wed Mar 24 04:25:23 2004 --- s2s/out.c Fri Oct 29 17:15:20 2004 *************** *** 254,262 **** /* connect */ out->fd = mio_connect(s2s->mio, pkt->port, pkt->ip, _out_mio_callback, (void *) out); out->s = sx_new(s2s->sx_env, out->fd, _out_sx_callback, (void *) out); - sx_client_init(out->s, S2S_DB_HEADER, "jabber:server", NULL, NULL, NULL); free(rkey); return; --- 254,277 ---- /* connect */ out->fd = mio_connect(s2s->mio, pkt->port, pkt->ip, _out_mio_callback, (void *) out); + if (out->fd < 0) { + log_write(out->s2s->log, LOG_NOTICE, "mio_connect error connecting to %s : %s (%d)", ipport, strerror(errno), errno); + } else { + log_write(out->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] outgoing connection", out->fd, out->ip, out->port); + } + out->s = sx_new(s2s->sx_env, out->fd, _out_sx_callback, (void *) out); + #ifdef HAVE_SSL + /* Send a stream version of 1.0 if we can do STARTTLS */ + if(out->s2s->sx_ssl != NULL && out->s2s->local_pemfile != NULL) { + sx_client_init(out->s, S2S_DB_HEADER, "jabber:server", pkt->to->domain, NULL, "1.0"); + } else { + sx_client_init(out->s, S2S_DB_HEADER, "jabber:server", NULL, NULL, NULL); + } + #else + sx_client_init(out->s, S2S_DB_HEADER, "jabber:server", NULL, NULL, NULL); + #endif free(rkey); return; *************** *** 465,470 **** --- 480,487 ---- /* generate the ip/port pair */ snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", out->ip, out->port); + log_write(out->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect", fd, out->ip, out->port); + xhash_zap(out->s2s->out, ipport); xhash_free(out->states); *************** *** 481,493 **** return 0; } static int _out_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { conn_t out = (conn_t) arg; sx_buf_t buf = (sx_buf_t) data; ! int len; sx_error_t *sxe; nad_t nad; - char *rkey; switch(e) { case event_WANT_READ: --- 498,524 ---- return 0; } + void send_dialbacks(conn_t out) + { + char *rkey; + + if (xhash_iter_first(out->routes)) { + log_debug(ZONE, "sending dialback packets for %s", out->key); + do { + xhash_iter_get(out->routes, (const char **) &rkey, NULL); + _out_dialback(out, rkey); + } while(xhash_iter_next(out->routes)); + } + + return; + } + static int _out_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { conn_t out = (conn_t) arg; sx_buf_t buf = (sx_buf_t) data; ! int len, ns, elem, starttls = 0; sx_error_t *sxe; nad_t nad; switch(e) { case event_WANT_READ: *************** *** 556,576 **** break; case event_STREAM: ! case event_OPEN: /* first time, bring them online */ if(!out->online) { log_debug(ZONE, "outgoing conn to %s is online", out->key); ! out->online = 1; ! ! /* kick off dialback for each route */ ! if(xhash_iter_first(out->routes)) ! do { ! xhash_iter_get(out->routes, (const char **) &rkey, NULL); ! _out_dialback(out, rkey); ! } while(xhash_iter_next(out->routes)); } break; --- 587,612 ---- break; + case event_OPEN: + log_debug(ZONE, "OPEN event for %s", out->key); + break; + case event_STREAM: ! /* check stream version - NULl = pre-xmpp (some jabber1 servers) */ ! log_debug(ZONE, "STREAM event for %s stream version is %s", out->key, out->s->res_version); /* first time, bring them online */ if(!out->online) { log_debug(ZONE, "outgoing conn to %s is online", out->key); ! /* 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)) { ! log_debug(ZONE, "no stream version, sending dialbacks for %s immediately", out->key); ! out->online = 1; ! send_dialbacks(out); ! } else ! log_debug(ZONE, "outgoing conn to %s - waiting for STREAM features", out->key); } break; *************** *** 578,583 **** --- 614,657 ---- case event_PACKET: nad = (nad_t) data; + /* watch for the features packet - STARTTLS and/or SASL*/ + if ((out->s->res_version!=NULL) + && NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_STREAMS) + && strncmp(uri_STREAMS, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_STREAMS)) == 0 + && NAD_ENAME_L(nad, 0) == 8 && strncmp("features", NAD_ENAME(nad, 0), 8) == 0) { + log_debug(ZONE, "got the stream features packet"); + + #ifdef HAVE_SSL + /* starttls if we can */ + if(out->s2s->sx_ssl != NULL && out->s2s->local_pemfile != NULL && s->ssf == 0) { + ns = nad_find_scoped_namespace(nad, uri_TLS, NULL); + if(ns >= 0) { + 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) { + starttls = 1; + nad_free(nad); + return 0; + } + log_write(out->s2s->log, LOG_ERR, "unable to establish encrypted session with peer"); + } + } + } + + /* If we're not establishing a starttls connection, send dialbacks */ + if (!starttls) { + log_debug(ZONE, "No STARTTLS, sending dialbacks for %s", out->key); + out->online = 1; + send_dialbacks(out); + } + #else + out->online = 1; + send_dialbacks(out); + #endif + } + + /* we only accept dialback packets */ if(NAD_ENS(nad, 0) < 0 || NAD_NURI_L(nad, NAD_ENS(nad, 0)) != 22 || strncmp("jabber:server:dialback", NAD_NURI(nad, NAD_ENS(nad, 0)), 22) != 0) { log_debug(ZONE, "got a non-dialback packet on an outgoing conn, dropping it"); *************** *** 640,646 **** /* key is valid */ if(nad_find_attr(nad, 0, -1, "type", "valid") >= 0) { ! log_write(out->s2s->log, LOG_NOTICE, "outgoing route '%s' is now valid; destination=%s, port %d", rkey, out->ip, out->port); xhash_put(out->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_VALID); /* !!! small leak here */ --- 714,720 ---- /* key is valid */ if(nad_find_attr(nad, 0, -1, "type", "valid") >= 0) { ! log_write(out->s2s->log, LOG_NOTICE, "outgoing route '%s' is now valid; destination=%s, port %d%s", rkey, out->ip, out->port, out->s->ssf ? ", SSL negotiated" : ""); xhash_put(out->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_VALID); /* !!! small leak here */ *************** *** 765,771 **** attr = nad_find_attr(nad, 0, -1, "type", "valid"); if(attr >= 0) { xhash_put(in->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_VALID); ! log_write(in->s2s->log, LOG_NOTICE, "incoming route '%s' is now valid; source=%s, port %d", rkey, in->ip, in->port); type = "valid"; } else { xhash_put(in->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_INVALID); --- 839,845 ---- attr = nad_find_attr(nad, 0, -1, "type", "valid"); if(attr >= 0) { xhash_put(in->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_VALID); ! log_write(in->s2s->log, LOG_NOTICE, "incoming route '%s' is now valid; source=%s, port %d%s", rkey, in->ip, in->port, in->s->ssf ? ", SSL negotiated" : ""); type = "valid"; } else { xhash_put(in->states, pstrdup(xhash_pool(out->states), rkey), (void *) conn_INVALID);