jabberd2  2.2.17
in.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 /*
24  * we handle incoming connections, and the packets that arrive on them.
25  *
26  * action points:
27  *
28  * event_STREAM - new incoming connection
29  * - create new dbconn (key stream id)
30  * - DONE
31  *
32  * event_PACKET: <result from='them' to='us'>key</result> - auth request
33  * - get dbconn for this sx
34  * - if dbconn state is valid
35  * - send result: <result to='them' from='us' type='valid'/>
36  * - DONE
37  * - out_packet(s2s, <verify to='them' from='us' id='stream id'>key</verify>)
38  * - DONE
39  *
40  * event_PACKET: <verify from='them' to='us' id='123'>key</verify> - validate their key
41  * - generate dbkey: sha1(secret+remote+id)
42  * - if their key matches dbkey
43  * - send them: <verify to='them' from='us' id='123' type='valid'/>
44  * - else
45  * - send them: <verify to='them' from='us' id='123' type='invalid'/>
46  * - DONE
47  *
48  * event_PACKET - they're trying to send us something
49  * - get dbconn for this sx
50  * - if dbconn state is invalid
51  * - drop packet
52  * - DONE
53  * - write packet to router
54  * - DONE
55  */
56 
57 /* forward decls */
58 static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg);
59 static void _in_result(conn_t in, nad_t nad);
60 static void _in_verify(conn_t in, nad_t nad);
61 static void _in_packet(conn_t in, nad_t nad);
62 
63 int in_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
64  conn_t in = (conn_t) arg;
65  s2s_t s2s = (s2s_t) arg;
66  struct sockaddr_storage sa;
67  int namelen = sizeof(sa), port, nbytes, flags = 0;
68  char ipport[INET6_ADDRSTRLEN + 17];
69 
70  switch(a) {
71  case action_READ:
72  log_debug(ZONE, "read action on fd %d", fd->fd);
73 
74  ioctl(fd->fd, FIONREAD, &nbytes);
75  if(nbytes == 0) {
76  sx_kill(in->s);
77  return 0;
78  }
79 
80  return sx_can_read(in->s);
81 
82  case action_WRITE:
83  log_debug(ZONE, "write action on fd %d", fd->fd);
84  return sx_can_write(in->s);
85 
86  case action_CLOSE:
87  log_debug(ZONE, "close action on fd %d", fd->fd);
88 
89  if (fd == s2s->server_fd) break;
90 
91  /* !!! logging */
92  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect, packets: %i", fd->fd, in->ip, in->port, in->packet_count);
93 
94  jqueue_push(in->s2s->dead, (void *) in->s, 0);
95 
96  /* remove from open streams hash if online, or open connections if not */
97  if (in->online)
98  xhash_zap(in->s2s->in, in->key);
99  else {
100  snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
101  xhash_zap(in->s2s->in_accept, ipport);
102  }
103 
104  jqueue_push(in->s2s->dead_conn, (void *) in, 0);
105 
106  break;
107 
108  case action_ACCEPT:
109  s2s = (s2s_t) arg;
110 
111  log_debug(ZONE, "accept action on fd %d", fd->fd);
112 
113  getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
114  port = j_inet_getport(&sa);
115 
116  log_write(s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming connection", fd->fd, (char *) data, port);
117 
118  /* new conn */
119  in = (conn_t) calloc(1, sizeof(struct conn_st));
120 
121  in->s2s = s2s;
122 
123  strncpy(in->ip, (char *) data, INET6_ADDRSTRLEN);
124  in->port = port;
125 
126  in->states = xhash_new(101);
127  in->states_time = xhash_new(101);
128 
129  in->fd = fd;
130 
131  in->init_time = time(NULL);
132 
133  in->s = sx_new(s2s->sx_env, in->fd->fd, _in_sx_callback, (void *) in);
134  mio_app(m, in->fd, in_mio_callback, (void *) in);
135 
136  if(s2s->stanza_size_limit != 0)
137  in->s->rbytesmax = s2s->stanza_size_limit;
138 
139  /* add to incoming connections hash */
140  snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
141  xhash_put(s2s->in_accept, pstrdup(xhash_pool(s2s->in_accept),ipport), (void *) in);
142 
143  flags = S2S_DB_HEADER;
144 #ifdef HAVE_SSL
145  if(s2s->sx_ssl != NULL)
146  flags |= SX_SSL_STARTTLS_OFFER;
147 #endif
148 #ifdef HAVE_LIBZ
149  if(s2s->compression)
150  flags |= SX_COMPRESS_OFFER;
151 #endif
152  sx_server_init(in->s, flags);
153  break;
154  }
155 
156  return 0;
157 }
158 
159 static int _in_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
160  conn_t in = (conn_t) arg;
161  sx_buf_t buf = (sx_buf_t) data;
162  int len;
163  sx_error_t *sxe;
164  nad_t nad;
165  char ipport[INET6_ADDRSTRLEN + 17];
166  jid_t from;
167  int attr;
168 
169  switch(e) {
170  case event_WANT_READ:
171  log_debug(ZONE, "want read");
172  mio_read(in->s2s->mio, in->fd);
173  break;
174 
175  case event_WANT_WRITE:
176  log_debug(ZONE, "want write");
177  mio_write(in->s2s->mio, in->fd);
178  break;
179 
180  case event_READ:
181  log_debug(ZONE, "reading from %d", in->fd->fd);
182 
183  /* do the read */
184  len = recv(in->fd->fd, buf->data, buf->len, 0);
185 
186  if(len < 0) {
187  if(MIO_WOULDBLOCK) {
188  buf->len = 0;
189  return 0;
190  }
191 
192  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
193 
194  sx_kill(s);
195 
196  return -1;
197  }
198 
199  else if(len == 0) {
200  /* they went away */
201  sx_kill(s);
202 
203  return -1;
204  }
205 
206  log_debug(ZONE, "read %d bytes", len);
207 
208  buf->len = len;
209 
210  return len;
211 
212  case event_WRITE:
213  log_debug(ZONE, "writing to %d", in->fd->fd);
214 
215  len = send(in->fd->fd, buf->data, buf->len, 0);
216  if(len >= 0) {
217  log_debug(ZONE, "%d bytes written", len);
218  return len;
219  }
220 
221  if(MIO_WOULDBLOCK)
222  return 0;
223 
224  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] write error: %s (%d)", in->fd->fd, in->ip, in->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
225 
226  sx_kill(s);
227 
228  return -1;
229 
230  case event_ERROR:
231  sxe = (sx_error_t *) data;
232  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", in->fd->fd, in->ip, in->port, sxe->generic, sxe->specific);
233 
234  break;
235 
236  case event_STREAM:
237  case event_OPEN:
238 
239  log_debug(ZONE, "STREAM or OPEN event from %s port %d (id %s)", in->ip, in->port, s->id);
240 
241  /* first time, bring them online */
242  if ((!in->online)||(strcmp(in->key,s->id)!=0)) {
243  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] incoming stream online (id %s)", in->fd->fd, in->ip, in->port, s->id);
244 
245  in->online = 1;
246 
247  /* record the id */
248  if (in->key != NULL) {
249  log_debug(ZONE,"adding new SSL stream id %s for stream id %s", s->id, in->key);
250 
251  /* remove the initial (non-SSL) stream id from the in connections hash */
252  xhash_zap(in->s2s->in, in->key);
253  free(in->key);
254  }
255 
256  in->key = strdup(s->id);
257 
258  /* track it - add to open streams hash and remove from new connections hash */
259  xhash_put(in->s2s->in, in->key, (void *) in);
260 
261  snprintf(ipport, INET6_ADDRSTRLEN + 16, "%s/%d", in->ip, in->port);
262  xhash_zap(in->s2s->in_accept, ipport);
263  }
264 
265  break;
266 
267  case event_PACKET:
268  /* we're counting packets */
269  in->packet_count++;
270  in->s2s->packet_count++;
271 
272  nad = (nad_t) data;
273 
274  /* update last packet timestamp */
275  in->last_packet = time(NULL);
276 
277  /* dialback packets */
278  if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_DIALBACK) && strncmp(uri_DIALBACK, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_DIALBACK)) == 0 &&
279  (in->s2s->require_tls == 0 || s->ssf > 0)) {
280  /* only result and verify mean anything */
281  if(NAD_ENAME_L(nad, 0) == 6) {
282  if(strncmp("result", NAD_ENAME(nad, 0), 6) == 0) {
283  _in_result(in, nad);
284  return 0;
285  }
286 
287  if(strncmp("verify", NAD_ENAME(nad, 0), 6) == 0) {
288  _in_verify(in, nad);
289  return 0;
290  }
291  }
292 
293  log_debug(ZONE, "unknown dialback packet, dropping it");
294 
295  nad_free(nad);
296  return 0;
297  }
298 
299  /*
300  * not dialback, so it has to be a normal-ish jabber packet:
301  * - jabber:client or jabber:server
302  * - message, presence or iq
303  * - has to and from attributes
304  */
305 
306  if(!(
307  /* must be jabber:client or jabber:server */
308  NAD_ENS(nad, 0) >= 0 &&
309  ((NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_CLIENT) && strncmp(uri_CLIENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_CLIENT)) == 0) ||
310  (NAD_NURI_L(nad, NAD_ENS(nad, 0)) == strlen(uri_SERVER) && strncmp(uri_SERVER, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_SERVER)) == 0)) && (
311  /* can be message */
312  (NAD_ENAME_L(nad, 0) == 7 && strncmp("message", NAD_ENAME(nad, 0), 7) == 0) ||
313  /* or presence */
314  (NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) ||
315  /* or iq */
316  (NAD_ENAME_L(nad, 0) == 2 && strncmp("iq", NAD_ENAME(nad, 0), 2) == 0)
317  ) &&
318  /* to and from required */
319  nad_find_attr(nad, 0, -1, "to", NULL) >= 0 && nad_find_attr(nad, 0, -1, "from", NULL) >= 0
320  )) {
321  log_debug(ZONE, "they sent us a non-jabber looking packet, dropping it");
322  nad_free(nad);
323  return 0;
324  }
325 
326  /* perform check against whitelist */
327  attr = nad_find_attr(nad, 0, -1, "from", NULL);
328  if(attr < 0 || (from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
329  log_debug(ZONE, "missing or invalid from on incoming packet, attr is %d", attr);
330  nad_free(nad);
331  return 0;
332  }
333 
334  if (in->s2s->enable_whitelist > 0 && (s2s_domain_in_whitelist(in->s2s, from->domain) == 0)) {
335  log_write(in->s2s->log, LOG_NOTICE, "received a packet not from a whitelisted domain %s, dropping it", from->domain);
336  jid_free(from);
337  nad_free(nad);
338  return 0;
339  }
340 
341  jid_free(from);
342 
343  _in_packet(in, nad);
344  return 0;
345 
346  case event_CLOSED:
347  if (in->fd != NULL) {
348  mio_close(in->s2s->mio, in->fd);
349  in->fd = NULL;
350  }
351  return -1;
352  }
353 
354  return 0;
355 }
356 
358 static void _in_result(conn_t in, nad_t nad) {
359  int attr, ns;
360  jid_t from, to;
361  char *rkey;
362  nad_t verify;
363  pkt_t pkt;
364  time_t now;
365 
366  attr = nad_find_attr(nad, 0, -1, "from", NULL);
367  if(attr < 0 || (from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
368  log_debug(ZONE, "missing or invalid from on db result packet");
369  nad_free(nad);
370  return;
371  }
372 
373  attr = nad_find_attr(nad, 0, -1, "to", NULL);
374  if(attr < 0 || (to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
375  log_debug(ZONE, "missing or invalid to on db result packet");
376  jid_free(from);
377  nad_free(nad);
378  return;
379  }
380 
381  rkey = s2s_route_key(NULL, to->domain, from->domain);
382 
383  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] received dialback auth request for route '%s'", in->fd->fd, in->ip, in->port, rkey);
384 
385  /* get current state */
386  if((conn_state_t) xhash_get(in->states, rkey) == conn_VALID) {
387  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] route '%s' is already valid: sending valid", in->fd->fd, in->ip, in->port, rkey);
388 
389  /* its already valid, just reply right now */
390  stanza_tofrom(nad, 0);
391  nad_set_attr(nad, 0, -1, "type", "valid", 5);
392  nad->elems[0].icdata = nad->elems[0].itail = -1;
393  nad->elems[0].lcdata = nad->elems[0].ltail = 0;
394 
395  sx_nad_write(in->s, nad);
396 
397  free(rkey);
398 
399  jid_free(from);
400  jid_free(to);
401 
402  return;
403  }
404 
405  /* not valid, so we need to verify */
406 
407  /* need the key */
408  if(NAD_CDATA_L(nad, 0) <= 0) {
409  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] no dialback key given with db result packet", in->fd->fd, in->ip, in->port, rkey);
410  free(rkey);
411  nad_free(nad);
412  jid_free(from);
413  jid_free(to);
414  return;
415  }
416 
417  log_debug(ZONE, "requesting verification for route %s", rkey);
418 
419  /* set the route status to INPROGRESS and set timestamp */
420  xhash_put(in->states, pstrdup(xhash_pool(in->states), rkey), (void *) conn_INPROGRESS);
421 
422  /* record the time that we set conn_INPROGRESS state */
423  now = time(NULL);
424  xhash_put(in->states_time, pstrdup(xhash_pool(in->states_time), rkey), (void *) now);
425 
426  free(rkey);
427 
428  /* new packet */
429  verify = nad_new();
430  ns = nad_add_namespace(verify, uri_DIALBACK, "db");
431 
432  nad_append_elem(verify, ns, "verify", 0);
433  nad_append_attr(verify, -1, "to", from->domain);
434  nad_append_attr(verify, -1, "from", to->domain);
435  nad_append_attr(verify, -1, "id", in->s->id);
436  nad_append_cdata(verify, NAD_CDATA(nad, 0), NAD_CDATA_L(nad, 0), 1);
437 
438  /* new packet */
439  pkt = (pkt_t) calloc(1, sizeof(struct pkt_st));
440 
441  pkt->nad = verify;
442 
443  pkt->to = from;
444  pkt->from = to;
445 
446  pkt->db = 1;
447 
448  /* its away */
449  out_packet(in->s2s, pkt);
450 
451  nad_free(nad);
452 }
453 
455 static void _in_verify(conn_t in, nad_t nad) {
456  int attr;
457  jid_t from, to;
458  char *id, *dbkey, *type;
459 
460  attr = nad_find_attr(nad, 0, -1, "from", NULL);
461  if(attr < 0 || (from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
462  log_debug(ZONE, "missing or invalid from on db verify packet");
463  nad_free(nad);
464  return;
465  }
466 
467  attr = nad_find_attr(nad, 0, -1, "to", NULL);
468  if(attr < 0 || (to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
469  log_debug(ZONE, "missing or invalid to on db verify packet");
470  jid_free(from);
471  nad_free(nad);
472  return;
473  }
474 
475  attr = nad_find_attr(nad, 0, -1, "id", NULL);
476  if(attr < 0) {
477  log_debug(ZONE, "missing id on db verify packet");
478  jid_free(from);
479  jid_free(to);
480  nad_free(nad);
481  return;
482  }
483 
484  if(NAD_CDATA_L(nad, 0) <= 0) {
485  log_debug(ZONE, "no cdata on db verify packet");
486  jid_free(from);
487  jid_free(to);
488  nad_free(nad);
489  return;
490  }
491 
492  /* extract the id */
493  id = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, attr) + 1));
494  snprintf(id, NAD_AVAL_L(nad, attr) + 1, "%.*s", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
495 
496  /* generate a dialback key */
497  dbkey = s2s_db_key(NULL, in->s2s->local_secret, from->domain, id);
498 
499  /* valid */
500  if(NAD_CDATA_L(nad, 0) == strlen(dbkey) && strncmp(dbkey, NAD_CDATA(nad, 0), NAD_CDATA_L(nad, 0)) == 0) {
501  log_debug(ZONE, "valid dialback key %s, verify succeeded", dbkey);
502  type = "valid";
503  } else {
504  log_debug(ZONE, "invalid dialback key %s, verify failed", dbkey);
505  type = "invalid";
506  }
507 
508  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] checking dialback verification from %s: sending %s", in->fd->fd, in->ip, in->port, from->domain, type);
509 
510  log_debug(ZONE, "letting them know");
511 
512  /* now munge the packet and send it back to them */
513  stanza_tofrom(nad, 0);
514  nad_set_attr(nad, 0, -1, "type", type, 0);
515  nad->elems[0].icdata = nad->elems[0].itail = -1;
516  nad->elems[0].lcdata = nad->elems[0].ltail = 0;
517 
518  sx_nad_write(in->s, nad);
519 
520  free(dbkey);
521  free(id);
522 
523  jid_free(from);
524  jid_free(to);
525 
526  return;
527 }
528 
530 static void _in_packet(conn_t in, nad_t nad) {
531  int elem, attr, ns, sns;
532  jid_t from, to;
533  char *rkey;
534 
535  attr = nad_find_attr(nad, 0, -1, "from", NULL);
536  if(attr < 0 || (from = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
537  log_debug(ZONE, "missing or invalid from on incoming packet");
538  nad_free(nad);
539  return;
540  }
541 
542  attr = nad_find_attr(nad, 0, -1, "to", NULL);
543  if(attr < 0 || (to = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) {
544  log_debug(ZONE, "missing or invalid to on incoming packet");
545  jid_free(from);
546  nad_free(nad);
547  return;
548  }
549 
550  rkey = s2s_route_key(NULL, to->domain, from->domain);
551 
552  log_debug(ZONE, "received packet from %s for %s", in->key, rkey);
553 
554  /* drop packets received on routes not valid on that connection as per XMPP 8.3.10 */
555  if((conn_state_t) xhash_get(in->states, rkey) != conn_VALID) {
556  log_write(in->s2s->log, LOG_NOTICE, "[%d] [%s, port=%d] dropping packet on unvalidated route: '%s'", in->fd->fd, in->ip, in->port, rkey);
557  free(rkey);
558  nad_free(nad);
559  jid_free(from);
560  jid_free(to);
561  return;
562  }
563 
564  free(rkey);
565 
566  /* its good, off to the router with it */
567 
568  log_debug(ZONE, "incoming packet on valid route, preparing it for the router");
569 
570  /* rewrite server packets into client packets */
571  ns = nad_find_namespace(nad, 0, uri_SERVER, NULL);
572  if(ns >= 0) {
573  if(nad->elems[0].ns == ns)
574  nad->elems[0].ns = nad->nss[nad->elems[0].ns].next;
575  else {
576  for(sns = nad->elems[0].ns; sns >= 0 && nad->nss[sns].next != ns; sns = nad->nss[sns].next);
577  nad->nss[sns].next = nad->nss[nad->nss[sns].next].next;
578  }
579  }
580 
581  /*
582  * If stanza is not in any namespace (either because we removed the
583  * jabber:server namespace above or because it's in the default
584  * namespace for this stream) then this packet is intended to be
585  * handled by sm (and not just routed through the server), so set the
586  * jabber:client namespace.
587  */
588  if(ns >= 0 || nad->elems[0].ns < 0) {
589  ns = nad_add_namespace(nad, uri_CLIENT, NULL);
590  for(elem = 0; elem < nad->ecur; elem++)
591  if(nad->elems[elem].ns == ns)
592  nad->elems[elem].ns = nad->nss[nad->elems[elem].ns].next;
593  nad->nss[ns].next = nad->elems[0].ns;
594  nad->elems[0].ns = ns;
595  nad->scope = -1;
596  }
597 
598  nad->elems[0].my_ns = nad->elems[0].ns;
599 
600  /* wrap up the packet */
601  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
602 
603  nad_wrap_elem(nad, 0, ns, "route");
604 
605  nad_set_attr(nad, 0, -1, "to", to->domain, 0);
606  nad_set_attr(nad, 0, -1, "from", in->s2s->id, 0); /* route is from s2s, not packet source */
607 
608  log_debug(ZONE, "sending packet to %s", to->domain);
609 
610  /* go */
611  sx_nad_write(in->s2s->router, nad);
612 
613  jid_free(from);
614  jid_free(to);
615 }