jabberd2  2.2.17
main.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #include "s2s.h"
22 
23 #include <stringprep.h>
24 
25 static sig_atomic_t s2s_shutdown = 0;
26 sig_atomic_t s2s_lost_router = 0;
27 static sig_atomic_t s2s_logrotate = 0;
28 
29 static void _s2s_signal(int signum) {
30  s2s_shutdown = 1;
31  s2s_lost_router = 0;
32 }
33 
34 static void _s2s_signal_hup(int signum) {
35  s2s_logrotate = 1;
36 }
37 
38 static void _s2s_signal_usr1(int signum)
39 {
40  set_debug_flag(0);
41 }
42 
43 static void _s2s_signal_usr2(int signum)
44 {
45  set_debug_flag(1);
46 }
47 
49 static void _s2s_pidfile(s2s_t s2s) {
50  char *pidfile;
51  FILE *f;
52  pid_t pid;
53 
54  pidfile = config_get_one(s2s->config, "pidfile", 0);
55  if(pidfile == NULL)
56  return;
57 
58  pid = getpid();
59 
60  if((f = fopen(pidfile, "w+")) == NULL) {
61  log_write(s2s->log, LOG_ERR, "couldn't open %s for writing: %s", pidfile, strerror(errno));
62  return;
63  }
64 
65  if(fprintf(f, "%d", pid) < 0) {
66  log_write(s2s->log, LOG_ERR, "couldn't write to %s: %s", pidfile, strerror(errno));
67  fclose(f);
68  return;
69  }
70 
71  fclose(f);
72 
73  log_write(s2s->log, LOG_INFO, "process id is %d, written to %s", pid, pidfile);
74 }
75 
77 static void _s2s_config_expand(s2s_t s2s) {
78  char *str, secret[41];
79  config_elem_t elem;
80  int i, r;
81 
83 
84  s2s->id = config_get_one(s2s->config, "id", 0);
85  if(s2s->id == NULL)
86  s2s->id = "s2s";
87 
88  s2s->router_ip = config_get_one(s2s->config, "router.ip", 0);
89  if(s2s->router_ip == NULL)
90  s2s->router_ip = "127.0.0.1";
91 
92  s2s->router_port = j_atoi(config_get_one(s2s->config, "router.port", 0), 5347);
93 
94  s2s->router_user = config_get_one(s2s->config, "router.user", 0);
95  if(s2s->router_user == NULL)
96  s2s->router_user = "jabberd";
97  s2s->router_pass = config_get_one(s2s->config, "router.pass", 0);
98  if(s2s->router_pass == NULL)
99  s2s->router_pass = "secret";
100 
101  s2s->router_pemfile = config_get_one(s2s->config, "router.pemfile", 0);
102 
103  s2s->retry_init = j_atoi(config_get_one(s2s->config, "router.retry.init", 0), 3);
104  s2s->retry_lost = j_atoi(config_get_one(s2s->config, "router.retry.lost", 0), 3);
105  if((s2s->retry_sleep = j_atoi(config_get_one(s2s->config, "router.retry.sleep", 0), 2)) < 1)
106  s2s->retry_sleep = 1;
107 
108  s2s->router_default = config_count(s2s->config, "router.non-default") ? 0 : 1;
109 
110  s2s->log_type = log_STDOUT;
111  if(config_get(s2s->config, "log") != NULL) {
112  if((str = config_get_attr(s2s->config, "log", 0, "type")) != NULL) {
113  if(strcmp(str, "file") == 0)
114  s2s->log_type = log_FILE;
115  else if(strcmp(str, "syslog") == 0)
116  s2s->log_type = log_SYSLOG;
117  }
118  }
119 
120  if(s2s->log_type == log_SYSLOG) {
121  s2s->log_facility = config_get_one(s2s->config, "log.facility", 0);
122  s2s->log_ident = config_get_one(s2s->config, "log.ident", 0);
123  if(s2s->log_ident == NULL)
124  s2s->log_ident = "jabberd/s2s";
125  } else if(s2s->log_type == log_FILE)
126  s2s->log_ident = config_get_one(s2s->config, "log.file", 0);
127 
128  s2s->packet_stats = config_get_one(s2s->config, "stats.packet", 0);
129 
130  if(s2s->local_ip == NULL)
131  s2s->local_ip = "0.0.0.0";
132 
133  /*
134  * If no origin IP is specified, use local IP as the originating one:
135  * it makes most sense, at least for SSL'ized connections.
136  * APPLE: make origin an array of addresses so that both IPv4 and IPv6 can be specified.
137  */
138  s2s->local_ip = config_get_one(s2s->config, "local.ip", 0);
139  if((elem = config_get(s2s->config, "local.origins.ip")) != NULL) {
140  s2s->origin_ips = elem->values;
141  s2s->origin_nips = elem->nvalues;
142  }
143  if (s2s->origin_nips == 0) {
144  s2s->origin_ips = (char **)malloc(sizeof(s2s->origin_ips));
145  s2s->origin_ips[0] = strdup(s2s->local_ip);
146  s2s->origin_nips = 1;
147  }
148 
149  s2s->local_port = j_atoi(config_get_one(s2s->config, "local.port", 0), 0);
150 
151  if(config_get(s2s->config, "local.secret") != NULL)
152  s2s->local_secret = strdup(config_get_one(s2s->config, "local.secret", 0));
153  else {
154  for(i = 0; i < 40; i++) {
155  r = (int) (36.0 * rand() / RAND_MAX);
156  secret[i] = (r >= 0 && r <= 9) ? (r + 48) : (r + 87);
157  }
158  secret[40] = '\0';
159 
160  s2s->local_secret = strdup(secret);
161  }
162 
163  if(s2s->local_secret == NULL)
164  s2s->local_secret = "secret";
165 
166  s2s->local_pemfile = config_get_one(s2s->config, "local.pemfile", 0);
167  s2s->local_cachain = config_get_one(s2s->config, "local.cachain", 0);
168  s2s->local_verify_mode = j_atoi(config_get_one(s2s->config, "local.verify-mode", 0), 0);
169 
170  s2s->io_max_fds = j_atoi(config_get_one(s2s->config, "io.max_fds", 0), 1024);
171 
172  s2s->compression = (config_get(s2s->config, "io.compression") != NULL);
173 
174  s2s->stanza_size_limit = j_atoi(config_get_one(s2s->config, "io.limits.stanzasize", 0), 0);
175  s2s->require_tls = j_atoi(config_get_one(s2s->config, "security.require_tls", 0), 0);
176  s2s->enable_whitelist = j_atoi(config_get_one(s2s->config, "security.enable_whitelist", 0), 0);
177  if((elem = config_get(s2s->config, "security.whitelist_domain")) != NULL) {
179  }
180 
181  s2s->check_interval = j_atoi(config_get_one(s2s->config, "check.interval", 0), 60);
182  s2s->check_queue = j_atoi(config_get_one(s2s->config, "check.queue", 0), 60);
183  s2s->check_keepalive = j_atoi(config_get_one(s2s->config, "check.keepalive", 0), 0);
184  s2s->check_idle = j_atoi(config_get_one(s2s->config, "check.idle", 0), 86400);
185  s2s->check_dnscache = j_atoi(config_get_one(s2s->config, "check.dnscache", 0), 300);
186  s2s->retry_limit = j_atoi(config_get_one(s2s->config, "check.retry", 0), 300);
187 
188  if((elem = config_get(s2s->config, "lookup.srv")) != NULL) {
189  s2s->lookup_srv = elem->values;
190  s2s->lookup_nsrv = elem->nvalues;
191  }
192 
193  s2s->resolve_aaaa = config_count(s2s->config, "lookup.resolve-ipv6") ? 1 : 0;
194  s2s->dns_cache_enabled = config_count(s2s->config, "lookup.no-cache") ? 0 : 1;
195  s2s->dns_bad_timeout = j_atoi(config_get_one(s2s->config, "lookup.bad-host-timeout", 0), 3600);
196  s2s->dns_min_ttl = j_atoi(config_get_one(s2s->config, "lookup.min-ttl", 0), 30);
197  if (s2s->dns_min_ttl < 5)
198  s2s->dns_min_ttl = 5;
199  s2s->dns_max_ttl = j_atoi(config_get_one(s2s->config, "lookup.max-ttl", 0), 86400);
200  s2s->etc_hosts_ttl = j_atoi(config_get_one(s2s->config, "lookup.etc-hosts-ttl", 0), 86400);
201  s2s->out_reuse = config_count(s2s->config, "out-conn-reuse") ? 1 : 0;
202 }
203 
204 static void _s2s_hosts_expand(s2s_t s2s)
205 {
206  char *realm;
207  config_elem_t elem;
208  char id[1024];
209  int i;
210 
211  elem = config_get(s2s->config, "local.id");
212 
213  if (elem) for(i = 0; i < elem->nvalues; i++) {
214  host_t host = (host_t) pmalloco(xhash_pool(s2s->hosts), sizeof(struct host_st));
215  if(!host) {
216  log_write(s2s->log, LOG_ERR, "cannot allocate memory for new host, aborting");
217  exit(1);
218  }
219 
220  realm = j_attr((const char **) elem->attrs[i], "realm");
221 
222  /* stringprep ids (domain names) so that they are in canonical form */
223  strncpy(id, elem->values[i], 1024);
224  id[1023] = '\0';
225  if (stringprep_nameprep(id, 1024) != 0) {
226  log_write(s2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
227  exit(1);
228  }
229 
230  host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(s2s->hosts), id);
231 
232  host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile");
233 
234  host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain");
235 
236  host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0);
237 
238 #ifdef HAVE_SSL
239  if(host->host_pemfile != NULL) {
240  if(s2s->sx_ssl == NULL) {
241  s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode);
242  if(s2s->sx_ssl == NULL) {
243  log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
244  host->host_pemfile = NULL;
245  }
246  } else {
247  if(sx_ssl_server_addcert(s2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode) != 0) {
248  log_write(s2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
249  host->host_pemfile = NULL;
250  }
251  }
252  }
253 #endif
254 
255  /* insert into vHosts xhash */
256  xhash_put(s2s->hosts, pstrdup(xhash_pool(s2s->hosts), id), host);
257 
258  log_write(s2s->log, LOG_NOTICE, "[%s] configured; realm=%s", id, host->realm);
259  }
260 }
261 
262 static int _s2s_router_connect(s2s_t s2s) {
263  log_write(s2s->log, LOG_NOTICE, "attempting connection to router at %s, port=%d", s2s->router_ip, s2s->router_port);
264 
265  s2s->fd = mio_connect(s2s->mio, s2s->router_port, s2s->router_ip, NULL, s2s_router_mio_callback, (void *) s2s);
266  if(s2s->fd == NULL) {
267  if(errno == ECONNREFUSED)
268  s2s_lost_router = 1;
269  log_write(s2s->log, LOG_NOTICE, "connection attempt to router failed: %s (%d)", MIO_STRERROR(MIO_ERROR), MIO_ERROR);
270  return 1;
271  }
272 
273  s2s->router = sx_new(s2s->sx_env, s2s->fd->fd, s2s_router_sx_callback, (void *) s2s);
274  sx_client_init(s2s->router, 0, NULL, NULL, NULL, "1.0");
275 
276  return 0;
277 }
278 
279 int _s2s_check_conn_routes(s2s_t s2s, conn_t conn, const char *direction)
280 {
281  char *rkey;
282  int rkeylen;
283  conn_state_t state;
284  time_t now, dialback_time;
285 
286  now = time(NULL);
287 
288  if(xhash_iter_first(conn->states))
289  do {
290  /* retrieve state in a separate operation, as sizeof(int) != sizeof(void *) on 64-bit platforms,
291  so passing a pointer to state in xhash_iter_get is unsafe */
292  xhash_iter_get(conn->states, (const char **) &rkey, &rkeylen, NULL);
293  state = (conn_state_t) xhash_getx(conn->states, rkey, rkeylen);
294 
295  if (state == conn_INPROGRESS) {
296  dialback_time = (time_t) xhash_getx(conn->states_time, rkey, rkeylen);
297 
298  if(now > dialback_time + s2s->check_queue) {
299  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback for %s route '%.*s' timed out", conn->fd->fd, conn->ip, conn->port, direction, rkeylen, rkey);
300 
301  xhash_zapx(conn->states, rkey, rkeylen);
302  xhash_zapx(conn->states_time, rkey, rkeylen);
303 
304  /* stream error */
305  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback timed out");
306 
307  /* close connection as per XMPP/RFC3920 */
308  sx_close(conn->s);
309 
310  /* indicate that we closed the connection */
311  return 0;
312  }
313  }
314  } while(xhash_iter_next(conn->states));
315 
316  /* all ok */
317  return 1;
318 }
319 
320 static void _s2s_time_checks(s2s_t s2s) {
321  conn_t conn;
322  time_t now;
323  char *rkey, *key;
324  int keylen;
325  jqueue_t q;
326  dnscache_t dns;
327  char *c;
328  int c_len;
329  union xhashv xhv;
330 
331  now = time(NULL);
332 
333  /* queue expiry */
334  if(s2s->check_queue > 0) {
335  if(xhash_iter_first(s2s->outq))
336  do {
337  xhv.jq_val = &q;
338  xhash_iter_get(s2s->outq, (const char **) &rkey, &keylen, xhv.val);
339 
340  log_debug(ZONE, "running time checks for %.*s", keylen, rkey);
341  c = memchr(rkey, '/', keylen);
342  c++;
343  c_len = keylen - (c - rkey);
344 
345  /* dns lookup timeout check first */
346  dns = xhash_getx(s2s->dnscache, c, c_len);
347  if(dns != NULL && dns->pending) {
348  log_debug(ZONE, "dns lookup pending for %.*s", c_len, c);
349  if(now > dns->init_time + s2s->check_queue) {
350  log_write(s2s->log, LOG_NOTICE, "dns lookup for %.*s timed out", c_len, c);
351 
352  /* bounce queue */
354 
355  /* expire pending dns entry */
356  xhash_zap(s2s->dnscache, dns->name);
357  xhash_free(dns->results);
358  if (dns->query != NULL) {
359  if (dns->query->query != NULL)
360  dns_cancel(NULL, dns->query->query);
361  xhash_free(dns->query->hosts);
362  xhash_free(dns->query->results);
363  free(dns->query->name);
364  free(dns->query);
365  }
366  free(dns);
367  }
368 
369  continue;
370  }
371 
372  /* get the conn */
373  conn = xhash_getx(s2s->out_dest, c, c_len);
374  if(conn == NULL) {
375  if(jqueue_size(q) > 0) {
376  /* no pending conn? perhaps it failed? */
377  log_debug(ZONE, "no pending connection for %.*s, bouncing %i packets in queue", c_len, c, jqueue_size(q));
378 
379  /* bounce queue */
381  }
382 
383  continue;
384  }
385 
386  /* connect timeout check */
387  if(!conn->online && now > conn->init_time + s2s->check_queue) {
388  dnsres_t bad;
389  char *ipport;
390 
391  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connection to %s timed out", conn->fd->fd, conn->ip, conn->port, c);
392 
393  if (s2s->dns_bad_timeout > 0) {
394  /* mark this host as bad */
395  ipport = dns_make_ipport(conn->ip, conn->port);
396  bad = xhash_get(s2s->dns_bad, ipport);
397  if (bad == NULL) {
398  bad = (dnsres_t) calloc(1, sizeof(struct dnsres_st));
399  bad->key = ipport;
400  xhash_put(s2s->dns_bad, ipport, bad);
401  } else {
402  free(ipport);
403  }
404  bad->expiry = time(NULL) + s2s->dns_bad_timeout;
405  }
406 
407  /* close connection as per XMPP/RFC3920 */
408  /* the close function will retry or bounce the queue */
409  sx_close(conn->s);
410  }
411  } while(xhash_iter_next(s2s->outq));
412  }
413 
414  /* expiry of connected routes in conn_INPROGRESS state */
415  if(s2s->check_queue > 0) {
416 
417  /* outgoing connections */
418  if(s2s->out_reuse) {
419  if(xhash_iter_first(s2s->out_host))
420  do {
421  xhv.conn_val = &conn;
422  xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
423  log_debug(ZONE, "checking dialback state for outgoing conn %.*s", keylen, key);
424  if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
425  log_debug(ZONE, "checking pending verify requests for outgoing conn %.*s", keylen, key);
426  if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
427  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
428  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
429  sx_close(conn->s);
430  }
431  }
432  } while(xhash_iter_next(s2s->out_host));
433  } else {
434  if(xhash_iter_first(s2s->out_dest))
435  do {
436  xhv.conn_val = &conn;
437  xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
438  log_debug(ZONE, "checking dialback state for outgoing conn %s (%s)", conn->dkey, conn->key);
439  if (_s2s_check_conn_routes(s2s, conn, "outgoing")) {
440  log_debug(ZONE, "checking pending verify requests for outgoing conn %s (%s)", conn->dkey, conn->key);
441  if (conn->verify > 0 && now > conn->last_verify + s2s->check_queue) {
442  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dialback verify request timed out", conn->fd->fd, conn->ip, conn->port);
443  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "dialback verify request timed out");
444  sx_close(conn->s);
445  }
446  }
447  } while(xhash_iter_next(s2s->out_dest));
448  }
449 
450  /* incoming open streams */
451  if(xhash_iter_first(s2s->in))
452  do {
453  xhv.conn_val = &conn;
454  xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
455 
456  log_debug(ZONE, "checking dialback state for incoming conn %.*s", keylen, key);
457  if (_s2s_check_conn_routes(s2s, conn, "incoming"))
458  /* if the connection is still valid, check that dialbacks have been initiated */
459  if(!xhash_count(conn->states) && now > conn->init_time + s2s->check_queue) {
460  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback started", conn->fd->fd, conn->ip, conn->port);
461  sx_error(conn->s, stream_err_CONNECTION_TIMEOUT, "no dialback initiated");
462  sx_close(conn->s);
463  }
464  } while(xhash_iter_next(s2s->in));
465 
466  /* incoming open connections (not yet streams) */
467  if(xhash_iter_first(s2s->in_accept))
468  do {
469  xhv.conn_val = &conn;
470  xhash_iter_get(s2s->in_accept, (const char **) &key, &keylen, xhv.val);
471 
472  log_debug(ZONE, "checking stream connection state for incoming conn %i", conn->fd->fd);
473  if(!conn->online && now > conn->init_time + s2s->check_queue) {
474  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] stream initiation timed out", conn->fd->fd, conn->ip, conn->port);
475  sx_close(conn->s);
476  }
477  } while(xhash_iter_next(s2s->in_accept));
478 
479  }
480 
481  /* keepalives */
482  if(s2s->out_reuse) {
483  if(xhash_iter_first(s2s->out_host))
484  do {
485  xhv.conn_val = &conn;
486  xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);
487 
488  if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
489  log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);
490 
491  sx_raw_write(conn->s, " ", 1);
492  }
493  } while(xhash_iter_next(s2s->out_host));
494  } else {
495  if(xhash_iter_first(s2s->out_dest))
496  do {
497  xhv.conn_val = &conn;
498  xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);
499 
500  if(s2s->check_keepalive > 0 && conn->last_activity > 0 && now > conn->last_activity + s2s->check_keepalive && conn->s->state >= state_STREAM) {
501  log_debug(ZONE, "sending keepalive for %d", conn->fd->fd);
502 
503  sx_raw_write(conn->s, " ", 1);
504  }
505  } while(xhash_iter_next(s2s->out_dest));
506  }
507 
508  /* idle timeouts - disconnect connections through which no packets have been sent for <idle> seconds */
509  if(s2s->check_idle > 0) {
510 
511  /* outgoing connections */
512  if(s2s->out_reuse) {
513  if(xhash_iter_first(s2s->out_host))
514  do {
515  xhv.conn_val = &conn;
516  xhash_iter_get(s2s->out_host, (const char **) &key, &keylen, xhv.val);
517  log_debug(ZONE, "checking idle state for %.*s", keylen, key);
518  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
519  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
520  sx_close(conn->s);
521  }
522  } while(xhash_iter_next(s2s->out_host));
523  } else {
524  if(xhash_iter_first(s2s->out_dest))
525  do {
526  xhv.conn_val = &conn;
527  xhash_iter_get(s2s->out_dest, (const char **) &key, &keylen, xhv.val);
528  log_debug(ZONE, "checking idle state for %s (%s)", conn->dkey, conn->key);
529  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
530  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
531  sx_close(conn->s);
532  }
533  } while(xhash_iter_next(s2s->out_dest));
534  }
535 
536  /* incoming connections */
537  if(xhash_iter_first(s2s->in))
538  do {
539  xhv.conn_val = &conn;
540  xhash_iter_get(s2s->in, (const char **) &key, &keylen, xhv.val);
541  log_debug(ZONE, "checking idle state for %.*s", keylen, key);
542  if (conn->last_packet > 0 && now > conn->last_packet + s2s->check_idle && conn->s->state >= state_STREAM) {
543  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] idle timeout", conn->fd->fd, conn->ip, conn->port);
544  sx_close(conn->s);
545  }
546  } while(xhash_iter_next(s2s->in));
547 
548  }
549 
550  return;
551 }
552 
553 static void _s2s_dns_expiry(s2s_t s2s) {
554  time_t now;
555  dnscache_t dns = NULL;
556  dnsres_t res = NULL;
557  union xhashv xhv;
558 
559  now = time(NULL);
560 
561  /* dnscache timeouts */
562  if(xhash_iter_first(s2s->dnscache))
563  do {
564  xhv.dns_val = &dns;
565  xhash_iter_get(s2s->dnscache, NULL, NULL, xhv.val);
566  if (dns && !dns->pending && now > dns->expiry) {
567  log_debug(ZONE, "expiring DNS cache for %s", dns->name);
568  xhash_iter_zap(s2s->dnscache);
569 
570  xhash_free(dns->results);
571  if (dns->query != NULL) {
572  if (dns->query->query != NULL)
573  dns_cancel(NULL, dns->query->query);
574  xhash_free(dns->query->hosts);
575  xhash_free(dns->query->results);
576  free(dns->query->name);
577  free(dns->query);
578  }
579  free(dns);
580  }
581  else if (dns == NULL) {
582  xhash_iter_zap(s2s->dnscache);
583  }
584  } while(xhash_iter_next(s2s->dnscache));
585 
586  if(xhash_iter_first(s2s->dns_bad))
587  do {
588  xhv.dnsres_val = &res;
589  xhash_iter_get(s2s->dns_bad, NULL, NULL, xhv.val);
590  if (res && now > res->expiry) {
591  log_debug(ZONE, "expiring DNS bad host %s", res->key);
592  xhash_iter_zap(s2s->dns_bad);
593 
594  free(res->key);
595  free(res);
596  }
597  else if (res == NULL) {
598  xhash_iter_zap(s2s->dns_bad);
599  }
600  } while(xhash_iter_next(s2s->dns_bad));
601 }
603 static int _mio_resolver_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
604 
605  switch(a) {
606  case action_READ:
607  log_debug(ZONE, "read action on fd %d", fd->fd);
608 
609  dns_ioevent(0, time(NULL));
610 
611  default:
612  break;
613  }
614 
615  return 0;
616 }
617 
618 /* Populate the whitelist_domains array with the config file values */
619 int _s2s_populate_whitelist_domains(s2s_t s2s, char **values, int nvalues) {
620  int i, j;
621  int elem_len;
622  s2s->whitelist_domains = (char **)malloc(sizeof(char*) * (nvalues));
623  memset(s2s->whitelist_domains, 0, (sizeof(char *) * (nvalues)));
624  for (i = 0, j = 0; i < nvalues; i++) {
625  elem_len = strlen(values[i]);
626  if (elem_len > MAX_DOMAIN_LEN) {
627  log_debug(ZONE, "whitelist domain element is too large, skipping");
628  continue;
629  }
630  if (elem_len == 0) {
631  log_debug(ZONE, "whitelist domain element is blank, skipping");
632  continue;
633  }
634  s2s->whitelist_domains[j] = (char *) malloc(sizeof(char) * (elem_len+1));
635  strncpy(s2s->whitelist_domains[j], values[i], elem_len);
636  s2s->whitelist_domains[j][elem_len] = '\0';
637  log_debug(ZONE, "s2s whitelist domain read from file: %s\n", s2s->whitelist_domains[j]);
638  j++;
639  }
640 
641  s2s->n_whitelist_domains = j;
642  log_debug(ZONE, "n_whitelist_domains = %d", s2s->n_whitelist_domains);
643  return 0;
644 }
645 
646 
647 /* Compare a domain with whitelist values.
648  The whitelist values may be FQDN or domain only (with no prepended hostname).
649  returns 1 on match, 0 on failure to match
650 */
651 int s2s_domain_in_whitelist(s2s_t s2s, char *in_domain) {
652  int segcount = 0;
653  int dotcount;
654  char **segments = NULL;
655  char **dst = NULL;
656  char *seg_tmp = NULL;
657  int seg_tmp_len;
658  char matchstr[MAX_DOMAIN_LEN + 1];
659  int domain_index;
660  int x, i;
661  int wl_index;
662  int wl_len;
663  int matchstr_len;
664  char domain[1024];
665  char *domain_ptr = &domain[0];
666  int domain_len;
667 
668  strncpy(domain, in_domain, sizeof(domain));
669  domain[sizeof(domain)-1] = '\0';
670  domain_len = strlen((const char *)&domain);
671 
672  if (domain_len <= 0) {
673  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: in_domain is empty");
674  return 0;
675  }
676 
677  if (domain_len > MAX_DOMAIN_LEN) {
678  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: in_domain is longer than %s chars", MAX_DOMAIN_LEN);
679  return 0;
680  }
681 
682  // first try matching the FQDN with whitelist domains
683  if (s2s->n_whitelist_domains <= 0)
684  return 0;
685 
686  for (wl_index =0; wl_index < s2s->n_whitelist_domains; wl_index++) {
687  wl_len = strlen(s2s->whitelist_domains[wl_index]);
688  if (!strncmp((const char *)&domain, s2s->whitelist_domains[wl_index], (domain_len > wl_len) ? domain_len : wl_len)) {
689  log_debug(ZONE, "domain \"%s\" matches whitelist entry", &domain);
690  return 1;
691  }
692  else {
693  //log_debug(ZONE, "domain: %s (len %d) does not match whitelist_domains[%d]: %s (len %d)", &domain, strlen((const char *)&domain), wl_index, s2s->whitelist_domains[wl_index], strlen(s2s->whitelist_domains[wl_index]));
694  }
695  }
696 
697  // break domain into segments for domain-only comparision
698  for (dotcount = 0, x = 0; domain[x] != '\0'; x++) {
699  if (domain[x] == '.')
700  dotcount++;
701  }
702 
703  segments = (char **)malloc(sizeof(char*) * (dotcount + 1));
704  if (segments == NULL) {
705  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: malloc() error");
706  return 0;
707  }
708  memset((char **)segments, 0, (sizeof(char*) * (dotcount + 1)));
709 
710  do {
711  if (segcount > (dotcount+1)) {
712  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: did not malloc enough room for domain segments; should never get here");
713  if (seg_tmp != NULL) {
714  free(seg_tmp);
715  seg_tmp = NULL;
716  }
717  for (x = 0; x < segcount; x++) {
718  free(segments[x]);
719  segments[x] = NULL;
720  }
721  free(segments);
722  segments = NULL;
723  return 0;
724  }
725  seg_tmp = strsep(&domain_ptr, ".");
726  if (seg_tmp == NULL) {
727  break;
728  }
729 
730  seg_tmp_len = strlen(seg_tmp);
731  if (seg_tmp_len > MAX_DOMAIN_LEN) {
732  log_write(s2s->log, LOG_NOTICE, "s2s_domain_in_whitelist: domain contains a segment greater than %s chars", MAX_DOMAIN_LEN);
733  if (seg_tmp != NULL) {
734  free(seg_tmp);
735  seg_tmp = NULL;
736  }
737  for (x = 0; x < segcount; x++) {
738  free(segments[x]);
739  segments[x] = NULL;
740  }
741  free(segments);
742  segments = NULL;
743  return 0;
744  }
745  dst = &segments[segcount];
746  *dst = (char *)malloc(seg_tmp_len + 1);
747  if (*dst != NULL) {
748  strncpy(*dst, seg_tmp, seg_tmp_len + 1);
749  (*dst)[seg_tmp_len] = '\0';
750  } else {
751  if (seg_tmp != NULL) {
752  free(seg_tmp);
753  seg_tmp = NULL;
754  }
755  for (x = 0; x < segcount; x++) {
756  free(segments[x]);
757  segments[x] = NULL;
758  }
759  free(segments);
760  segments = NULL;
761  log_write(s2s->log, LOG_ERR, "s2s_domain_in_whitelist: malloc() error");
762  return 0;
763  }
764  segcount++;
765  } while (seg_tmp != NULL);
766 
767  if (segcount > 1) {
768  for (domain_index = segcount-2; domain_index > 0; domain_index--) {
769  matchstr[0] = '\0';
770  for (i = domain_index; i < segcount; i++) {
771  if (i > domain_index) {
772  strncat((char *)&matchstr, ".", sizeof(matchstr));
773  matchstr[sizeof(matchstr)-1] = '\0';
774  }
775  strncat((char *)&matchstr, (char *)segments[i], sizeof(matchstr));
776  matchstr[sizeof(matchstr)-1] = '\0';
777  }
778  for (wl_index = 0; wl_index < s2s->n_whitelist_domains; wl_index++) {
779  wl_len = strlen(s2s->whitelist_domains[wl_index]);
780  matchstr_len = strlen((const char *)&matchstr);
781  if (!strncmp((const char *)&matchstr, s2s->whitelist_domains[wl_index], (wl_len > matchstr_len ? wl_len : matchstr_len))) {
782  log_debug(ZONE, "matchstr \"%s\" matches whitelist entry", &matchstr);
783  for (x = 0; x < segcount; x++) {
784  free(segments[x]);
785  segments[x] = NULL;
786  }
787  free(segments);
788  segments = NULL;
789  return 1;
790  }
791  else {
792  //log_debug(ZONE, "matchstr: %s (len %d) does not match whitelist_domains[%d]: %s (len %d)", &matchstr, strlen((const char *)&matchstr), wl_index, s2s->whitelist_domains[wl_index], strlen(s2s->whitelist_domains[wl_index]));
793  }
794  }
795  }
796  }
797  for (x = 0; x < segcount; x++) {
798  free(segments[x]);
799  segments[x] = NULL;
800  }
801  free(segments);
802  segments = NULL;
803 
804  return 0;
805 }
806 
807 JABBER_MAIN("jabberd2s2s", "Jabber 2 S2S", "Jabber Open Source Server: Server to Server", "jabberd2router\0")
808 {
809  s2s_t s2s;
810  char *config_file;
811  int optchar;
812  conn_t conn;
813  jqueue_t q;
814  dnscache_t dns;
815  dnsres_t res;
816  union xhashv xhv;
817  time_t check_time = 0, now = 0;
818  const char *cli_id = 0;
819 
820 #ifdef HAVE_UMASK
821  umask((mode_t) 0027);
822 #endif
823 
824  srand(time(NULL));
825 
826 #ifdef HAVE_WINSOCK2_H
827 /* get winsock running */
828  {
829  WORD wVersionRequested;
830  WSADATA wsaData;
831  int err;
832 
833  wVersionRequested = MAKEWORD( 2, 2 );
834 
835  err = WSAStartup( wVersionRequested, &wsaData );
836  if ( err != 0 ) {
837  /* !!! tell user that we couldn't find a usable winsock dll */
838  return 0;
839  }
840  }
841 #endif
842 
843  jabber_signal(SIGINT, _s2s_signal);
844  jabber_signal(SIGTERM, _s2s_signal);
845 #ifdef SIGHUP
847 #endif
848 #ifdef SIGPIPE
849  jabber_signal(SIGPIPE, SIG_IGN);
850 #endif
853 
854 
855  s2s = (s2s_t) calloc(1, sizeof(struct s2s_st));
856 
857  /* load our config */
858  s2s->config = config_new();
859 
860  config_file = CONFIG_DIR "/s2s.xml";
861 
862  /* cmdline parsing */
863  while((optchar = getopt(argc, argv, "Dc:hi:?")) >= 0)
864  {
865  switch(optchar)
866  {
867  case 'c':
868  config_file = optarg;
869  break;
870  case 'D':
871 #ifdef DEBUG
872  set_debug_flag(1);
873 #else
874  printf("WARN: Debugging not enabled. Ignoring -D.\n");
875 #endif
876  break;
877  case 'i':
878  cli_id = optarg;
879  break;
880  case 'h': case '?': default:
881  fputs(
882  "s2s - jabberd server-to-server connector (" VERSION ")\n"
883  "Usage: s2s <options>\n"
884  "Options are:\n"
885  " -c <config> config file to use [default: " CONFIG_DIR "/s2s.xml]\n"
886  " -i id Override <id> config element\n"
887 #ifdef DEBUG
888  " -D Show debug output\n"
889 #endif
890  ,
891  stdout);
892  config_free(s2s->config);
893  free(s2s);
894  return 1;
895  }
896  }
897 
898  if(config_load_with_id(s2s->config, config_file, cli_id) != 0) {
899  fputs("s2s: couldn't load config, aborting\n", stderr);
900  config_free(s2s->config);
901  free(s2s);
902  return 2;
903  }
904 
905  _s2s_config_expand(s2s);
906 
907  s2s->log = log_new(s2s->log_type, s2s->log_ident, s2s->log_facility);
908  log_write(s2s->log, LOG_NOTICE, "starting up (interval=%i, queue=%i, keepalive=%i, idle=%i)", s2s->check_interval, s2s->check_queue, s2s->check_keepalive, s2s->check_idle);
909 
910  _s2s_pidfile(s2s);
911 
912  s2s->outq = xhash_new(401);
913  s2s->out_host = xhash_new(401);
914  s2s->out_dest = xhash_new(401);
915  s2s->in = xhash_new(401);
916  s2s->in_accept = xhash_new(401);
917  s2s->dnscache = xhash_new(401);
918  s2s->dns_bad = xhash_new(401);
919 
920  s2s->dead = jqueue_new();
921  s2s->dead_conn = jqueue_new();
922 
923  s2s->sx_env = sx_env_new();
924 
925 #ifdef HAVE_SSL
926  /* get the ssl context up and running */
927  if(s2s->local_pemfile != NULL) {
929 
930  if(s2s->sx_ssl == NULL) {
931  log_write(s2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to peers");
932  s2s->local_pemfile = NULL;
933  } else
934  log_debug(ZONE, "loaded pemfile for SSL connections to peers");
935  }
936 
937  /* try and get something online, so at least we can encrypt to the router */
938  if(s2s->sx_ssl == NULL && s2s->router_pemfile != NULL) {
939  s2s->sx_ssl = sx_env_plugin(s2s->sx_env, sx_ssl_init, NULL, s2s->router_pemfile, NULL, NULL);
940  if(s2s->sx_ssl == NULL) {
941  log_write(s2s->log, LOG_ERR, "failed to load router SSL pemfile, channel to router will not be SSL encrypted");
942  s2s->router_pemfile = NULL;
943  }
944  }
945 #endif
946 
947 #ifdef HAVE_LIBZ
948  /* get compression up and running */
949  if(s2s->compression)
951 #endif
952 
953  /* get sasl online */
954  s2s->sx_sasl = sx_env_plugin(s2s->sx_env, sx_sasl_init, "xmpp", NULL, NULL);
955  if(s2s->sx_sasl == NULL) {
956  log_write(s2s->log, LOG_ERR, "failed to initialise SASL context, aborting");
957  exit(1);
958  }
959 
960  /* hosts mapping */
961  s2s->hosts = xhash_new(1021);
962  _s2s_hosts_expand(s2s);
963 
964  s2s->sx_db = sx_env_plugin(s2s->sx_env, s2s_db_init);
965 
966  s2s->mio = mio_new(s2s->io_max_fds);
967 
968  if((s2s->udns_fd = dns_init(NULL, 1)) < 0) {
969  log_write(s2s->log, LOG_ERR, "unable to initialize dns library, aborting");
970  exit(1);
971  }
972  s2s->udns_mio_fd = mio_register(s2s->mio, s2s->udns_fd, _mio_resolver_callback, (void *) s2s);
973 
974  s2s->retry_left = s2s->retry_init;
975  _s2s_router_connect(s2s);
976 
977  while(!s2s_shutdown) {
978  mio_run(s2s->mio, dns_timeouts(0, 5, time(NULL)));
979 
980  now = time(NULL);
981 
982  if(s2s_logrotate) {
984 
985  log_write(s2s->log, LOG_NOTICE, "reopening log ...");
986  log_free(s2s->log);
987  s2s->log = log_new(s2s->log_type, s2s->log_ident, s2s->log_facility);
988  log_write(s2s->log, LOG_NOTICE, "log started");
989 
990  s2s_logrotate = 0;
991  }
992 
993  if(s2s_lost_router) {
994  if(s2s->retry_left < 0) {
995  log_write(s2s->log, LOG_NOTICE, "attempting reconnect");
996  sleep(s2s->retry_sleep);
997  s2s_lost_router = 0;
998  if (s2s->router) sx_free(s2s->router);
999  _s2s_router_connect(s2s);
1000  }
1001 
1002  else if(s2s->retry_left == 0) {
1003  s2s_shutdown = 1;
1004  }
1005 
1006  else {
1007  log_write(s2s->log, LOG_NOTICE, "attempting reconnect (%d left)", s2s->retry_left);
1008  s2s->retry_left--;
1009  sleep(s2s->retry_sleep);
1010  s2s_lost_router = 0;
1011  if (s2s->router) sx_free(s2s->router);
1012  _s2s_router_connect(s2s);
1013  }
1014  }
1015 
1016  /* this has to be read unconditionally - we could receive replies to queries we cancelled */
1017  mio_read(s2s->mio, s2s->udns_mio_fd);
1018 
1019  /* cleanup dead sx_ts */
1020  while(jqueue_size(s2s->dead) > 0)
1021  sx_free((sx_t) jqueue_pull(s2s->dead));
1022 
1023  /* cleanup dead conn_ts */
1024  while(jqueue_size(s2s->dead_conn) > 0) {
1025  conn = (conn_t) jqueue_pull(s2s->dead_conn);
1026  xhash_free(conn->states);
1027  xhash_free(conn->states_time);
1028  xhash_free(conn->routes);
1029 
1030  free(conn->key);
1031  free(conn->dkey);
1032  free(conn);
1033  }
1034 
1035  /* time checks */
1036  if(s2s->check_interval > 0 && now >= s2s->next_check) {
1037  log_debug(ZONE, "running time checks");
1038 
1039  _s2s_time_checks(s2s);
1040 
1041  s2s->next_check = now + s2s->check_interval;
1042  log_debug(ZONE, "next time check at %d", s2s->next_check);
1043  }
1044 
1045  /* dnscache expiry */
1046  if(s2s->check_dnscache > 0 && now >= s2s->next_expiry) {
1047  log_debug(ZONE, "running dns expiry");
1048 
1049  _s2s_dns_expiry(s2s);
1050 
1051  s2s->next_expiry = now + s2s->check_dnscache;
1052  log_debug(ZONE, "next dns expiry at %d", s2s->next_expiry);
1053  }
1054 
1055  if(now > check_time + 60) {
1056 #ifdef POOL_DEBUG
1057  pool_stat(1);
1058 #endif
1059  if(s2s->packet_stats != NULL) {
1060  int fd = open(s2s->packet_stats, O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
1061  if(fd) {
1062  char buf[100];
1063  int len = snprintf(buf, 100, "%lld\n", s2s->packet_count);
1064  write(fd, buf, len);
1065  close(fd);
1066  } else {
1067  log_write(s2s->log, LOG_ERR, "failed to write packet statistics to: %s", s2s->packet_stats);
1068  s2s_shutdown = 1;
1069  }
1070  }
1071 
1072  check_time = now;
1073  }
1074  }
1075 
1076  log_write(s2s->log, LOG_NOTICE, "shutting down");
1077 
1078  /* close active streams gracefully */
1079  xhv.conn_val = &conn;
1080  if(s2s->out_reuse) {
1081  if(xhash_iter_first(s2s->out_host))
1082  do {
1083  xhash_iter_get(s2s->out_host, NULL, NULL, xhv.val);
1084  if(conn) {
1085  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1087  sx_close(conn->s);
1088  }
1089  } while(xhash_iter_next(s2s->out_host));
1090  } else {
1091  if(xhash_iter_first(s2s->out_dest))
1092  do {
1093  xhash_iter_get(s2s->out_dest, NULL, NULL, xhv.val);
1094  if(conn) {
1095  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1097  sx_close(conn->s);
1098  }
1099  } while(xhash_iter_next(s2s->out_dest));
1100  }
1101 
1102  if(xhash_iter_first(s2s->in))
1103  do {
1104  xhash_iter_get(s2s->in, NULL, NULL, xhv.val);
1105  if(conn) {
1106  sx_error(conn->s, stream_err_SYSTEM_SHUTDOWN, "s2s shutdown");
1108  sx_close(conn->s);
1109  }
1110  } while(xhash_iter_next(s2s->in));
1111 
1112  if(xhash_iter_first(s2s->in_accept))
1113  do {
1114  xhash_iter_get(s2s->in_accept, NULL, NULL, xhv.val);
1115  if(conn) {
1117  sx_close(conn->s);
1118  }
1119  } while(xhash_iter_next(s2s->in_accept));
1120 
1121 
1122  /* remove dead streams */
1123  while(jqueue_size(s2s->dead) > 0)
1124  sx_free((sx_t) jqueue_pull(s2s->dead));
1125 
1126  /* cleanup dead conn_ts */
1127  while(jqueue_size(s2s->dead_conn) > 0) {
1128  conn = (conn_t) jqueue_pull(s2s->dead_conn);
1129  xhash_free(conn->states);
1130  xhash_free(conn->states_time);
1131  xhash_free(conn->routes);
1132 
1133  if(conn->key != NULL) free(conn->key);
1134  if(conn->dkey != NULL) free(conn->dkey);
1135  free(conn);
1136  }
1137 
1138  /* free outgoing queues */
1139  xhv.jq_val = &q;
1140  if(xhash_iter_first(s2s->outq))
1141  do {
1142  xhash_iter_get(s2s->outq, NULL, NULL, xhv.val);
1143  while (jqueue_size(q) > 0)
1145  free(q->key);
1146  jqueue_free(q);
1147  } while(xhash_iter_next(s2s->outq));
1148 
1149  /* walk & free resolve queues */
1150  xhv.dns_val = &dns;
1151  if(xhash_iter_first(s2s->dnscache))
1152  do {
1153  xhash_iter_get(s2s->dnscache, NULL, NULL, xhv.val);
1154  xhash_free(dns->results);
1155  if (dns->query != NULL) {
1156  if (dns->query->query != NULL)
1157  dns_cancel(NULL, dns->query->query);
1158  xhash_free(dns->query->hosts);
1159  xhash_free(dns->query->results);
1160  free(dns->query->name);
1161  free(dns->query);
1162  }
1163  free(dns);
1164  } while(xhash_iter_next(s2s->dnscache));
1165 
1166  xhv.dnsres_val = &res;
1167  if(xhash_iter_first(s2s->dns_bad))
1168  do {
1169  xhash_iter_get(s2s->dns_bad, NULL, NULL, xhv.val);
1170  free(res->key);
1171  free(res);
1172  } while(xhash_iter_next(s2s->dns_bad));
1173 
1174  if (dns_active(NULL) > 0)
1175  log_debug(ZONE, "there are still active dns queries (%d)", dns_active(NULL));
1176  dns_close(NULL);
1177 
1178  /* close mio */
1179  mio_close(s2s->mio, s2s->udns_mio_fd);
1180  if(s2s->fd != NULL)
1181  mio_close(s2s->mio, s2s->fd);
1182  if(s2s->server_fd != NULL)
1183  mio_close(s2s->mio, s2s->server_fd);
1184 
1185  /* free hashes */
1186  xhash_free(s2s->outq);
1187  xhash_free(s2s->out_host);
1188  xhash_free(s2s->out_dest);
1189  xhash_free(s2s->in);
1190  xhash_free(s2s->in_accept);
1191  xhash_free(s2s->dnscache);
1192  xhash_free(s2s->dns_bad);
1193  xhash_free(s2s->hosts);
1194 
1195  jqueue_free(s2s->dead);
1196  jqueue_free(s2s->dead_conn);
1197 
1198  sx_free(s2s->router);
1199 
1200  sx_env_free(s2s->sx_env);
1201 
1202  mio_free(s2s->mio);
1203 
1204  log_free(s2s->log);
1205 
1206  config_free(s2s->config);
1207 
1208  free(s2s->local_secret);
1209  free(s2s);
1210 
1211 #ifdef POOL_DEBUG
1212  pool_stat(1);
1213 #endif
1214 
1215  return 0;
1216 }