jabberd2  2.5.0
c2s.c
Go to the documentation of this file.
1 /* vim: set et ts=4 sw=4: */
2 /*
3  * jabberd - Jabber Open Source Server
4  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
5  * Ryan Eatmon, Robert Norris
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
20  */
21 
22 #include "c2s.h"
23 #include <stringprep.h>
24 
25 static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
26  sess_t sess = (sess_t) arg;
27  sx_buf_t buf = (sx_buf_t) data;
28  int rlen, len, ns, elem, attr;
29  sx_error_t *sxe;
30  nad_t nad;
31  char root[9];
32  bres_t bres, ires;
33  stream_redirect_t redirect;
34 
35  switch(e) {
36  case event_WANT_READ:
37  log_debug(ZONE, "want read");
38  mio_read(sess->c2s->mio, sess->fd);
39  break;
40 
41  case event_WANT_WRITE:
42  log_debug(ZONE, "want write");
43  mio_write(sess->c2s->mio, sess->fd);
44  break;
45 
46  case event_READ:
47  log_debug(ZONE, "reading from %d", sess->fd->fd);
48 
49  /* check rate limits */
50  if(sess->rate != NULL) {
51  if(rate_check(sess->rate) == 0) {
52 
53  /* inform the app if we haven't already */
54  if(!sess->rate_log) {
55  if(s->state >= state_STREAM && sess->resources != NULL)
56  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] is being byte rate limited", sess->fd->fd, jid_user(sess->resources->jid));
57  else
58  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] is being byte rate limited", sess->fd->fd, sess->ip, sess->port);
59 
60  sess->rate_log = 1;
61  }
62 
63  return -1;
64  }
65 
66  /* find out how much we can have */
67  rlen = rate_left(sess->rate);
68  if(rlen > buf->len)
69  rlen = buf->len;
70  }
71 
72  /* no limit, just read as much as we can */
73  else
74  rlen = buf->len;
75 
76  /* do the read */
77  len = recv(sess->fd->fd, buf->data, rlen, 0);
78 
79  /* update rate limits */
80  if(sess->rate != NULL)
81  rate_add(sess->rate, len);
82 
83  if(len < 0) {
84  if(MIO_WOULDBLOCK) {
85  buf->len = 0;
86  return 0;
87  }
88 
89  if(s->state >= state_STREAM && sess->resources != NULL)
90  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] read error: %s (%d)", sess->fd->fd, jid_user(sess->resources->jid), MIO_STRERROR(MIO_ERROR), MIO_ERROR);
91  else
92  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] read error: %s (%d)", sess->fd->fd, sess->ip, sess->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
93 
94  sx_kill(s);
95 
96  return -1;
97  }
98 
99  else if(len == 0) {
100  /* they went away */
101  sx_kill(s);
102 
103  return -1;
104  }
105 
106  log_debug(ZONE, "read %d bytes", len);
107 
108  buf->len = len;
109 
110  return len;
111 
112  case event_WRITE:
113  log_debug(ZONE, "writing to %d", sess->fd->fd);
114 
115  len = send(sess->fd->fd, buf->data, buf->len, 0);
116  if(len >= 0) {
117  log_debug(ZONE, "%d bytes written", len);
118  return len;
119  }
120 
121  if(MIO_WOULDBLOCK)
122  return 0;
123 
124  if(s->state >= state_OPEN && sess->resources != NULL)
125  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] write error: %s (%d)", sess->fd->fd, jid_user(sess->resources->jid), MIO_STRERROR(MIO_ERROR), MIO_ERROR);
126  else
127  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s. port=%d] write error: %s (%d)", sess->fd->fd, sess->ip, sess->port, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
128 
129  sx_kill(s);
130 
131  return -1;
132 
133  case event_ERROR:
134  sxe = (sx_error_t *) data;
135  if(sess->resources != NULL)
136  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] error: %s (%s)", sess->fd->fd, jid_user(sess->resources->jid), sxe->generic, sxe->specific);
137  else
138  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] error: %s (%s)", sess->fd->fd, sess->ip, sess->port, sxe->generic, sxe->specific);
139 
140  break;
141 
142  case event_STREAM:
143 
144  if(s->req_to == NULL) {
145  log_debug(ZONE, "no stream to provided, closing");
146  sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header");
147  sx_close(s);
148 
149  return 0;
150  }
151 
152  /* send a see-other-host error if we're configured to do so */
153  redirect = (stream_redirect_t) xhash_get(sess->c2s->stream_redirects, s->req_to);
154  if (redirect != NULL) {
155  log_debug(ZONE, "redirecting client's stream using see-other-host for domain: '%s'", s->req_to);
156  len = strlen(redirect->to_address) + strlen(redirect->to_port) + 1;
157  char *other_host = (char *) malloc(len+1);
158  snprintf(other_host, len+1, "%s:%s", redirect->to_address, redirect->to_port);
160  free(other_host);
161  sx_close(s);
162 
163  return 0;
164  }
165 
166  /* setup the host */
167  sess->host = xhash_get(sess->c2s->hosts, s->req_to);
168 
169  if(sess->host == NULL && sess->c2s->vhost == NULL) {
170  log_debug(ZONE, "no host available for requested domain '%s'", s->req_to);
171  sx_error(s, stream_err_HOST_UNKNOWN, "service requested for unknown domain");
172  sx_close(s);
173 
174  return 0;
175  }
176 
177  if(xhash_get(sess->c2s->sm_avail, s->req_to) == NULL) {
178  log_debug(ZONE, "sm for domain '%s' is not online", s->req_to);
179  sx_error(s, stream_err_HOST_GONE, "session manager for requested domain is not available");
180  sx_close(s);
181 
182  return 0;
183  }
184 
185  if(sess->host == NULL) {
186  /* create host on-fly */
187  sess->host = (host_t) pmalloc(xhash_pool(sess->c2s->hosts), sizeof(struct host_st));
188  memcpy(sess->host, sess->c2s->vhost, sizeof(struct host_st));
189  sess->host->realm = pstrdup(xhash_pool(sess->c2s->hosts), s->req_to);
190  xhash_put(sess->c2s->hosts, pstrdup(xhash_pool(sess->c2s->hosts), s->req_to), sess->host);
191  }
192 
193 #ifdef HAVE_SSL
194  if(sess->host->host_pemfile != NULL)
195  sess->s->flags |= SX_SSL_STARTTLS_OFFER;
196  if(sess->host->host_require_starttls)
197  sess->s->flags |= SX_SSL_STARTTLS_REQUIRE;
198 #endif
199  break;
200 
201  case event_PACKET:
202  /* we're counting packets */
203  sess->packet_count++;
204  sess->c2s->packet_count++;
205 
206  /* check rate limits */
207  if(sess->stanza_rate != NULL) {
208  if(rate_check(sess->stanza_rate) == 0) {
209 
210  /* inform the app if we haven't already */
211  if(!sess->stanza_rate_log) {
212  if(s->state >= state_STREAM && sess->resources != NULL)
213  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] is being stanza rate limited", sess->fd->fd, jid_user(sess->resources->jid));
214  else
215  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] is being stanza rate limited", sess->fd->fd, sess->ip, sess->port);
216 
217  sess->stanza_rate_log = 1;
218  }
219  }
220 
221  /* update rate limits */
222  rate_add(sess->stanza_rate, 1);
223  }
224 
225  nad = (nad_t) data;
226 
227  /* we only want (message|presence|iq) in jabber:client, everything else gets dropped */
228  snprintf(root, 9, "%.*s", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0));
229  if(NAD_ENS(nad, 0) != nad_find_namespace(nad, 0, uri_CLIENT, NULL) ||
230  (strcmp(root, "message") != 0 && strcmp(root, "presence") != 0 && strcmp(root, "iq") != 0)) {
231  nad_free(nad);
232  return 0;
233  }
234 
235  /* resource bind */
236  if((ns = nad_find_scoped_namespace(nad, uri_BIND, NULL)) >= 0 && (elem = nad_find_elem(nad, 0, ns, "bind", 1)) >= 0 && nad_find_attr(nad, 0, -1, "type", "set") >= 0) {
237  bres_t bres;
238  jid_t jid = jid_new(sess->s->auth_id, -1);
239 
240  /* get the resource */
241  elem = nad_find_elem(nad, elem, ns, "resource", 1);
242 
243  /* user-specified resource */
244  if(elem >= 0) {
245  char resource_buf[1024];
246 
247  if(NAD_CDATA_L(nad, elem) == 0) {
248  log_debug(ZONE, "empty resource specified on bind");
250 
251  return 0;
252  }
253 
254  snprintf(resource_buf, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
255  /* Put resource into JID */
256  if (jid == NULL || jid_reset_components(jid, jid->node, jid->domain, resource_buf) == NULL) {
257  log_debug(ZONE, "invalid jid data");
259 
260  return 0;
261  }
262 
263  /* check if resource already bound */
264  for(bres = sess->resources; bres != NULL; bres = bres->next)
265  if(strcmp(bres->jid->resource, jid->resource) == 0){
266  log_debug(ZONE, "resource /%s already bound - generating", jid->resource);
268  }
269  }
270  else {
271  /* generate random resource */
272  log_debug(ZONE, "no resource given - generating");
274  }
275 
276  /* attach new bound jid holder */
277  bres = (bres_t) calloc(1, sizeof(struct bres_st));
278  bres->jid = jid;
279  if(sess->resources != NULL) {
280  for(ires = sess->resources; ires->next != NULL; ires = ires->next);
281  ires->next = bres;
282  } else
283  sess->resources = bres;
284 
285  sess->bound += 1;
286 
287  log_write(sess->c2s->log, LOG_NOTICE, "[%d] bound: jid=%s", sess->s->tag, jid_full(bres->jid));
288 
289  /* build a result packet, we'll send this back to the client after we have a session for them */
290  sess->result = nad_new();
291 
292  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
293 
294  nad_append_elem(sess->result, ns, "iq", 0);
295  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
296 
297  attr = nad_find_attr(nad, 0, -1, "id", NULL);
298  if(attr >= 0)
299  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
300 
301  ns = nad_add_namespace(sess->result, uri_BIND, NULL);
302 
303  nad_append_elem(sess->result, ns, "bind", 1);
304  nad_append_elem(sess->result, ns, "jid", 2);
305  nad_append_cdata(sess->result, jid_full(bres->jid), strlen(jid_full(bres->jid)), 3);
306 
307  /* our local id */
308  sprintf(bres->c2s_id, "%d", sess->s->tag);
309 
310  /* start a session with the sm */
311  sm_start(sess, bres);
312 
313  /* finished with the nad */
314  nad_free(nad);
315 
316  /* handled */
317  return 0;
318  }
319 
320  /* resource unbind */
321  if((ns = nad_find_scoped_namespace(nad, uri_BIND, NULL)) >= 0 && (elem = nad_find_elem(nad, 0, ns, "unbind", 1)) >= 0 && nad_find_attr(nad, 0, -1, "type", "set") >= 0) {
322  char resource_buf[1024];
323  bres_t bres;
324 
325  /* get the resource */
326  elem = nad_find_elem(nad, elem, ns, "resource", 1);
327 
328  if(elem < 0 || NAD_CDATA_L(nad, elem) == 0) {
329  log_debug(ZONE, "no/empty resource given to unbind");
331 
332  return 0;
333  }
334 
335  snprintf(resource_buf, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
336  if(stringprep_xmpp_resourceprep(resource_buf, 1024) != 0) {
337  log_debug(ZONE, "cannot resourceprep");
339 
340  return 0;
341  }
342 
343  /* check if resource bound */
344  for(bres = sess->resources; bres != NULL; bres = bres->next)
345  if(strcmp(bres->jid->resource, resource_buf) == 0)
346  break;
347 
348  if(bres == NULL) {
349  log_debug(ZONE, "resource /%s not bound", resource_buf);
351 
352  return 0;
353  }
354 
355  /* build a result packet, we'll send this back to the client after we close a session for them */
356  sess->result = nad_new();
357 
358  ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);
359 
360  nad_append_elem(sess->result, ns, "iq", 0);
361  nad_set_attr(sess->result, 0, -1, "type", "result", 6);
362 
363  attr = nad_find_attr(nad, 0, -1, "id", NULL);
364  if(attr >= 0)
365  nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
366 
367  /* end a session with the sm */
368  sm_end(sess, bres);
369 
370  /* finished with the nad */
371  nad_free(nad);
372 
373  /* handled */
374  return 0;
375  }
376 
377  /* pre-session requests */
378  if(!sess->active && sess->sasl_authd && sess->result == NULL && strcmp(root, "iq") == 0 && nad_find_attr(nad, 0, -1, "type", "set") >= 0) {
379  log_debug(ZONE, "unrecognised pre-session packet, bye");
380  log_write(sess->c2s->log, LOG_NOTICE, "[%d] unrecognized pre-session packet, closing stream", sess->s->tag);
381 
382  sx_error(s, stream_err_NOT_AUTHORIZED, "unrecognized pre-session stanza");
383  sx_close(s);
384 
385  nad_free(nad);
386  return 0;
387  }
388 
389 #ifdef HAVE_SSL
390  /* drop packets if they have to starttls and they haven't */
391  if((sess->s->flags & SX_SSL_STARTTLS_REQUIRE) && sess->s->ssf == 0) {
392  log_debug(ZONE, "pre STARTTLS packet, dropping");
393  log_write(sess->c2s->log, LOG_NOTICE, "[%d] got pre STARTTLS packet, dropping", sess->s->tag);
394 
395  sx_error(s, stream_err_POLICY_VIOLATION, "STARTTLS is required for this stream");
396 
397  nad_free(nad);
398  return 0;
399  }
400 #endif
401 
402  /* handle iq:auth packets */
403  if(authreg_process(sess->c2s, sess, nad) == 0)
404  return 0;
405 
406  /* drop it if no session */
407  if(!sess->active) {
408  log_debug(ZONE, "pre-session packet, bye");
409  log_write(sess->c2s->log, LOG_NOTICE, "[%d] packet sent before session start, closing stream", sess->s->tag);
410 
411  sx_error(s, stream_err_NOT_AUTHORIZED, "stanza sent before session start");
412  sx_close(s);
413 
414  nad_free(nad);
415  return 0;
416  }
417 
418  /* validate 'from' */
419  assert(sess->resources != NULL);
420  if(sess->bound > 1) {
421  bres = NULL;
422  if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0)
423  for(bres = sess->resources; bres != NULL; bres = bres->next)
424  if(strncmp(jid_full(bres->jid), NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0)
425  break;
426 
427  if(bres == NULL) {
428  if(attr >= 0) {
429  log_debug(ZONE, "packet from: %.*s that has not bound the resource", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
430  } else {
431  log_debug(ZONE, "packet without 'from' on multiple resource stream");
432  }
433 
435 
436  return 0;
437  }
438  } else
439  bres = sess->resources;
440 
441  /* pass it on to the session manager */
442  sm_packet(sess, bres, nad);
443 
444  break;
445 
446  case event_OPEN:
447 
448  /* only send a result and bring us online if this wasn't a sasl auth */
449  if(strlen(s->auth_method) < 4 || strncmp("SASL", s->auth_method, 4) != 0) {
450  /* return the auth result to the client */
451  sx_nad_write(s, sess->result);
452  sess->result = NULL;
453 
454  /* we're good to go */
455  sess->active = 1;
456  }
457 
458  /* they sasl auth'd, so we only want the new-style session start */
459  else {
460  log_write(sess->c2s->log, LOG_NOTICE, "[%d] %s authentication succeeded: %s %s:%d %s",
461  sess->s->tag, &sess->s->auth_method[5],
462  sess->s->auth_id, sess->s->ip, sess->s->port, _sx_flags(sess->s)
463  );
464  sess->sasl_authd = 1;
465  }
466 
467  break;
468 
469  case event_CLOSED:
470  mio_close(sess->c2s->mio, sess->fd);
471  sess->fd = NULL;
472  return -1;
473  }
474 
475  return 0;
476 }
477 
478 static int _c2s_client_accept_check(c2s_t c2s, mio_fd_t fd, const char *ip) {
479  rate_t rt;
480 
481  if(access_check(c2s->access, ip) == 0) {
482  log_write(c2s->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd->fd, ip);
483  return 1;
484  }
485 
486  if(c2s->conn_rate_total != 0) {
487  rt = (rate_t) xhash_get(c2s->conn_rates, ip);
488  if(rt == NULL) {
490  xhash_put(c2s->conn_rates, pstrdup(xhash_pool(c2s->conn_rates), ip), (void *) rt);
491  pool_cleanup(xhash_pool(c2s->conn_rates), (void (*)(void *)) rate_free, rt);
492  }
493 
494  if(rate_check(rt) == 0) {
495  log_write(c2s->log, LOG_NOTICE, "[%d] [%s] is being connect rate limited", fd->fd, ip);
496  return 1;
497  }
498 
499  rate_add(rt, 1);
500  }
501 
502  return 0;
503 }
504 
505 static int _c2s_client_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
506  sess_t sess = (sess_t) arg;
507  c2s_t c2s = (c2s_t) arg;
508  bres_t bres;
509  struct sockaddr_storage sa;
510  socklen_t namelen = sizeof(sa);
511  int port, nbytes, flags = 0;
512 
513  switch(a) {
514  case action_READ:
515  log_debug(ZONE, "read action on fd %d", fd->fd);
516 
517  /* they did something */
518  sess->last_activity = time(NULL);
519 
520  ioctl(fd->fd, FIONREAD, &nbytes);
521  if(nbytes == 0) {
522  sx_kill(sess->s);
523  return 0;
524  }
525 
526  return sx_can_read(sess->s);
527 
528  case action_WRITE:
529  log_debug(ZONE, "write action on fd %d", fd->fd);
530 
531  return sx_can_write(sess->s);
532 
533  case action_CLOSE:
534  log_debug(ZONE, "close action on fd %d", fd->fd);
535 
536  log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] disconnect jid=%s, packets: %i, bytes: %d", sess->fd->fd, sess->ip, sess->port, ((sess->resources)?((char*) jid_full(sess->resources->jid)):"unbound"), sess->packet_count, sess->s->tbytes);
537 
538  /* tell the sm to close their session */
539  if(sess->active)
540  for(bres = sess->resources; bres != NULL; bres = bres->next)
541  sm_end(sess, bres);
542 
543  /* call the session end callback to allow for authreg
544  * module to cleanup private data */
545  if(sess->host && sess->host->ar->sess_end != NULL)
546  (sess->host->ar->sess_end)(sess->host->ar, sess);
547 
548  /* force free authreg_private if pointer is still set */
549  if (sess->authreg_private != NULL) {
550  free(sess->authreg_private);
551  sess->authreg_private = NULL;
552  }
553 
554  jqueue_push(sess->c2s->dead, (void *) sess->s, 0);
555 
556  xhash_zap(sess->c2s->sessions, sess->skey);
557 
558  jqueue_push(sess->c2s->dead_sess, (void *) sess, 0);
559 
560  break;
561 
562  case action_ACCEPT:
563  log_debug(ZONE, "accept action on fd %d", fd->fd);
564 
565  if(getpeername(fd->fd, (struct sockaddr *) &sa, &namelen) < 0)
566  return 1;
567  port = j_inet_getport(&sa);
568 
569  log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connect", fd->fd, (char *) data, port);
570 
571  if(_c2s_client_accept_check(c2s, fd, (char *) data) != 0)
572  return 1;
573 
574  sess = (sess_t) calloc(1, sizeof(struct sess_st));
575 
576  sess->c2s = c2s;
577 
578  sess->fd = fd;
579 
580  sess->ip = strdup((char *) data);
581  sess->port = port;
582 
583  /* they did something */
584  sess->last_activity = time(NULL);
585 
586  sess->s = sx_new(c2s->sx_env, fd->fd, _c2s_client_sx_callback, (void *) sess);
587  mio_app(m, fd, _c2s_client_mio_callback, (void *) sess);
588 
589  if(c2s->stanza_size_limit != 0)
590  sess->s->rbytesmax = c2s->stanza_size_limit;
591 
592  if(c2s->byte_rate_total != 0)
594 
595  if(c2s->stanza_rate_total != 0)
597 
598  /* give IP to SX */
599  sess->s->ip = sess->ip;
600  sess->s->port = sess->port;
601 
602  /* find out which port this is */
603  if(getsockname(fd->fd, (struct sockaddr *) &sa, &namelen) < 0)
604  return 1;
605  port = j_inet_getport(&sa);
606 
607  /* remember it */
608  sprintf(sess->skey, "%d", fd->fd);
609  xhash_put(c2s->sessions, sess->skey, (void *) sess);
610 
611  flags = SX_SASL_OFFER;
612 #ifdef HAVE_SSL
613  /* go ssl wrappermode if they're on the ssl port */
614  if(port == c2s->local_ssl_port)
615  flags |= SX_SSL_WRAPPER;
616 #endif
617 #ifdef HAVE_LIBZ
618  if(c2s->compression && !(sess->s->flags & SX_WEBSOCKET_WRAPPER))
619  flags |= SX_COMPRESS_OFFER;
620 #endif
621  sx_server_init(sess->s, flags);
622 
623  break;
624  }
625 
626  return 0;
627 }
628 
629 static void _c2s_component_presence(c2s_t c2s, nad_t nad) {
630  int attr;
631  char from[1024];
632  sess_t sess;
633  union xhashv xhv;
634 
635  if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) < 0) {
636  nad_free(nad);
637  return;
638  }
639 
640  strncpy(from, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
641  from[NAD_AVAL_L(nad, attr)] = '\0';
642 
643  if(nad_find_attr(nad, 0, -1, "type", NULL) < 0) {
644  log_debug(ZONE, "component available from '%s'", from);
645 
646  log_debug(ZONE, "sm for serviced domain '%s' online", from);
647 
648  xhash_put(c2s->sm_avail, pstrdup(xhash_pool(c2s->sm_avail), from), (void *) 1);
649 
650  nad_free(nad);
651  return;
652  }
653 
654  if(nad_find_attr(nad, 0, -1, "type", "unavailable") < 0) {
655  nad_free(nad);
656  return;
657  }
658 
659  log_debug(ZONE, "component unavailable from '%s'", from);
660 
661  if(xhash_get(c2s->sm_avail, from) != NULL) {
662  log_debug(ZONE, "sm for serviced domain '%s' offline", from);
663 
664  if(xhash_iter_first(c2s->sessions))
665  do {
666  xhv.sess_val = &sess;
667  xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val);
668 
669  if(sess->resources != NULL && strcmp(sess->resources->jid->domain, from) == 0) {
670  log_debug(ZONE, "killing session %s", jid_user(sess->resources->jid));
671 
672  sess->active = 0;
673  if(sess->s) sx_close(sess->s);
674  }
675  } while(xhash_iter_next(c2s->sessions));
676 
677  xhash_zap(c2s->sm_avail, from);
678  }
679 }
680 
681 int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
682  c2s_t c2s = (c2s_t) arg;
683  sx_buf_t buf = (sx_buf_t) data;
684  sx_error_t *sxe;
685  nad_t nad;
686  int len, elem, from, c2sid, smid, action, id, ns, attr, scan, replaced;
687  char skey[44];
688  sess_t sess;
689  bres_t bres, ires;
690  char *smcomp;
691 
692  switch(e) {
693  case event_WANT_READ:
694  log_debug(ZONE, "want read");
695  mio_read(c2s->mio, c2s->fd);
696  break;
697 
698  case event_WANT_WRITE:
699  log_debug(ZONE, "want write");
700  mio_write(c2s->mio, c2s->fd);
701  break;
702 
703  case event_READ:
704  log_debug(ZONE, "reading from %d", c2s->fd->fd);
705 
706  /* do the read */
707  len = recv(c2s->fd->fd, buf->data, buf->len, 0);
708 
709  if(len < 0) {
710  if(MIO_WOULDBLOCK) {
711  buf->len = 0;
712  return 0;
713  }
714 
715  log_write(c2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
716 
717  sx_kill(s);
718 
719  return -1;
720  }
721 
722  else if(len == 0) {
723  /* they went away */
724  sx_kill(s);
725 
726  return -1;
727  }
728 
729  log_debug(ZONE, "read %d bytes", len);
730 
731  buf->len = len;
732 
733  return len;
734 
735  case event_WRITE:
736  log_debug(ZONE, "writing to %d", c2s->fd->fd);
737 
738  len = send(c2s->fd->fd, buf->data, buf->len, 0);
739  if(len >= 0) {
740  log_debug(ZONE, "%d bytes written", len);
741  return len;
742  }
743 
744  if(MIO_WOULDBLOCK)
745  return 0;
746 
747  log_write(c2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
748 
749  sx_kill(s);
750 
751  return -1;
752 
753  case event_ERROR:
754  sxe = (sx_error_t *) data;
755  log_write(c2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific);
756 
757  if(sxe->code == SX_ERR_AUTH)
758  sx_close(s);
759 
760  break;
761 
762  case event_STREAM:
763  break;
764 
765  case event_OPEN:
766  log_write(c2s->log, LOG_NOTICE, "connection to router established");
767 
768  /* set connection attempts counter */
769  c2s->retry_left = c2s->retry_lost;
770 
771  nad = nad_new();
772  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
773  nad_append_elem(nad, ns, "bind", 0);
774  nad_append_attr(nad, -1, "name", c2s->id);
775 
776  log_debug(ZONE, "requesting component bind for '%s'", c2s->id);
777 
778  sx_nad_write(c2s->router, nad);
779 
780  return 0;
781 
782  case event_PACKET:
783  nad = (nad_t) data;
784 
785  /* drop unqualified packets */
786  if(NAD_ENS(nad, 0) < 0) {
787  nad_free(nad);
788  return 0;
789  }
790 
791  /* watch for the features packet */
792  if(s->state == state_STREAM) {
793  if(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) {
794  log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping");
795  nad_free(nad);
796  return 0;
797  }
798 
799 #ifdef HAVE_SSL
800  /* starttls if we can */
801  if(c2s->sx_ssl != NULL && c2s->router_pemfile != NULL && s->ssf == 0) {
802  ns = nad_find_scoped_namespace(nad, uri_TLS, NULL);
803  if(ns >= 0) {
804  elem = nad_find_elem(nad, 0, ns, "starttls", 1);
805  if(elem >= 0) {
807  nad_free(nad);
808  return 0;
809  }
810  log_write(c2s->log, LOG_ERR, "unable to establish encrypted session with router");
811  }
812  }
813  }
814 #endif
815 
816  /* !!! pull the list of mechanisms, and choose the best one.
817  * if there isn't an appropriate one, error and bail */
818 
819  /* authenticate */
820  sx_sasl_auth(c2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", c2s->router_user, c2s->router_pass);
821 
822  nad_free(nad);
823  return 0;
824  }
825 
826  /* watch for the bind response */
827  if(s->state == state_OPEN && !c2s->online) {
828  if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0 || NAD_ENAME_L(nad, 0) != 4 || strncmp("bind", NAD_ENAME(nad, 0), 4) != 0) {
829  log_debug(ZONE, "got a packet from router, but we're not online, dropping");
830  nad_free(nad);
831  return 0;
832  }
833 
834  /* catch errors */
835  attr = nad_find_attr(nad, 0, -1, "error", NULL);
836  if(attr >= 0) {
837  log_write(c2s->log, LOG_ERR, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
838  exit(1);
839  }
840 
841  log_debug(ZONE, "coming online");
842 
843  /* if we're coming online for the first time, setup listening sockets */
844 #ifdef HAVE_SSL
845  if(c2s->server_fd == 0 && c2s->server_ssl_fd == 0) {
846 #else
847  if(c2s->server_fd == 0) {
848 #endif
849  if(c2s->local_port != 0) {
850  c2s->server_fd = mio_listen(c2s->mio, c2s->local_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s);
851  if(c2s->server_fd == NULL)
852  log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_port);
853  else
854  log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", c2s->local_ip, c2s->local_port);
855  } else
856  c2s->server_fd = NULL;
857 
858 #ifdef HAVE_SSL
859  if(c2s->local_ssl_port != 0 && c2s->local_pemfile != NULL) {
860  c2s->server_ssl_fd = mio_listen(c2s->mio, c2s->local_ssl_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s);
861  if(c2s->server_ssl_fd == NULL)
862  log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_ssl_port);
863  else
864  log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for SSL connections", c2s->local_ip, c2s->local_ssl_port);
865  } else
866  c2s->server_ssl_fd = NULL;
867 #endif
868  }
869 
870 #ifdef HAVE_SSL
871  if(c2s->server_fd == NULL && c2s->server_ssl_fd == NULL && c2s->pbx_pipe == NULL) {
872  log_write(c2s->log, LOG_ERR, "both normal and SSL ports are disabled, nothing to do!");
873 #else
874  if(c2s->server_fd == NULL && c2s->pbx_pipe == NULL) {
875  log_write(c2s->log, LOG_ERR, "server port is disabled, nothing to do!");
876 #endif
877  exit(1);
878  }
879 
880  /* open PBX integration FIFO */
881  if(c2s->pbx_pipe != NULL)
882  c2s_pbx_init(c2s);
883 
884  /* we're online */
885  c2s->online = c2s->started = 1;
886  log_write(c2s->log, LOG_NOTICE, "ready for connections", c2s->id);
887 
888  nad_free(nad);
889  return 0;
890  }
891 
892  /* need component packets */
893  if(NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT) || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0) {
894  log_debug(ZONE, "wanted component packet, dropping");
895  nad_free(nad);
896  return 0;
897  }
898 
899  /* component presence */
900  if(NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) {
901  _c2s_component_presence(c2s, nad);
902  return 0;
903  }
904 
905  /* we want route */
906  if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) {
907  log_debug(ZONE, "wanted {component}route, dropping");
908  nad_free(nad);
909  return 0;
910  }
911 
912  /* only handle unicasts */
913  if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) {
914  log_debug(ZONE, "non-unicast packet, dropping");
915  nad_free(nad);
916  return 0;
917  }
918 
919  /* need some payload */
920  if(nad->ecur == 1) {
921  log_debug(ZONE, "no route payload, dropping");
922  nad_free(nad);
923  return 0;
924  }
925 
926  ns = nad_find_namespace(nad, 1, uri_SESSION, NULL);
927  if(ns < 0) {
928  log_debug(ZONE, "not a c2s packet, dropping");
929  nad_free(nad);
930  return 0;
931  }
932 
933  /* figure out the session */
934  c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL);
935  if(c2sid < 0) {
936  log_debug(ZONE, "no c2s id on payload, dropping");
937  nad_free(nad);
938  return 0;
939  }
940  snprintf(skey, sizeof(skey), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid));
941 
942  /* find the session, quietly drop if we don't have it */
943  sess = xhash_get(c2s->sessions, skey);
944  if(sess == NULL) {
945  /* if we get this, the SM probably thinks the session is still active
946  * so we need to tell SM to free it up */
947  log_debug(ZONE, "no session for %s", skey);
948 
949  /* check if it's a started action; otherwise we could end up in an infinite loop
950  * trying to tell SM to close in response to errors */
951  action = nad_find_attr(nad, 1, -1, "action", NULL);
952  if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) {
953  int target;
954  bres_t tres;
955  sess_t tsess;
956 
957  log_write(c2s->log, LOG_NOTICE, "session %s does not exist; telling sm to close", skey);
958 
959  /* we don't have a session and we don't have a resource; we need to forge them both
960  * to get SM to close stuff */
961  target = nad_find_attr(nad, 1, -1, "target", NULL);
962  smid = nad_find_attr(nad, 1, ns, "sm", NULL);
963  if(target < 0 || smid < 0) {
964  const char *buf;
965  int len;
966  nad_print(nad, 0, &buf, &len);
967  log_write(c2s->log, LOG_NOTICE, "sm sent an invalid start packet: %.*s", len, buf );
968  nad_free(nad);
969  return 0;
970  }
971 
972  /* build temporary resource to close session for */
973  tres = (bres_t) calloc(1, sizeof(struct bres_st));
974  tres->jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target));
975 
976  strncpy(tres->c2s_id, skey, sizeof(tres->c2s_id));
977  snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
978 
979  /* make a temporary session */
980  tsess = (sess_t) calloc(1, sizeof(struct sess_st));
981  tsess->c2s = c2s;
982  tsess->result = nad_new();
983  strncpy(tsess->skey, skey, sizeof(tsess->skey));
984 
985  /* end a session with the sm */
986  sm_end(tsess, tres);
987 
988  /* free our temporary messes */
989  nad_free(tsess->result);
990  jid_free(tres->jid); //TODO will this crash?
991  free(tsess);
992  free(tres);
993  }
994 
995  nad_free(nad);
996  return 0;
997  }
998 
999  /* if they're pre-stream, then this is leftovers from a previous session */
1000  if(sess->s && sess->s->state < state_STREAM) {
1001  log_debug(ZONE, "session %s is pre-stream", skey);
1002 
1003  nad_free(nad);
1004  return 0;
1005  }
1006 
1007  /* check the sm session id if they gave us one */
1008  smid = nad_find_attr(nad, 1, ns, "sm", NULL);
1009 
1010  /* get the action attribute */
1011  action = nad_find_attr(nad, 1, -1, "action", NULL);
1012 
1013  /* first user created packets - these are out of session */
1014  if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("created", NAD_AVAL(nad, action), 7) == 0) {
1015 
1016  nad_free(nad);
1017 
1018  if(sess->result) {
1019  /* return the result to the client */
1020  sx_nad_write(sess->s, sess->result);
1021  sess->result = NULL;
1022  } else {
1023  log_write(sess->c2s->log, LOG_WARNING, "user created for session %s which is already gone", skey);
1024  }
1025 
1026  return 0;
1027  }
1028 
1029  /* route errors */
1030  if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) {
1031  log_debug(ZONE, "routing error");
1032 
1033  if(sess->s) {
1034  sx_error(sess->s, stream_err_INTERNAL_SERVER_ERROR, "internal server error");
1035  sx_close(sess->s);
1036  }
1037 
1038  nad_free(nad);
1039  return 0;
1040  }
1041 
1042  /* all other packets need to contain an sm ID */
1043  if (smid < 0) {
1044  log_debug(ZONE, "received packet from sm without an sm ID, dropping");
1045  nad_free(nad);
1046  return 0;
1047  }
1048 
1049  /* find resource that we got packet for */
1050  bres = NULL;
1051  if(smid >= 0)
1052  for(bres = sess->resources; bres != NULL; bres = bres->next){
1053  if(bres->sm_id[0] == '\0' || (strlen(bres->sm_id) == NAD_AVAL_L(nad, smid) && strncmp(bres->sm_id, NAD_AVAL(nad, smid), NAD_AVAL_L(nad, smid)) == 0))
1054  break;
1055  }
1056  if(bres == NULL) {
1057  jid_t jid = NULL;
1058  bres_t tres = NULL;
1059 
1060  /* if it's a failure, just drop it */
1061  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1062  nad_free(nad);
1063  return 0;
1064  }
1065 
1066  /* build temporary resource to close session for */
1067  tres = (bres_t) calloc(1, sizeof(struct bres_st));
1068  if(sess->s) {
1069  jid = jid_new(sess->s->auth_id, -1);
1070  sprintf(tres->c2s_id, "%d", sess->s->tag);
1071  }
1072  else {
1073  /* does not have SX - extract values from route packet */
1074  int c2sid, target;
1075  c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL);
1076  target = nad_find_attr(nad, 1, -1, "target", NULL);
1077  if(c2sid < 0 || target < 0) {
1078  log_debug(ZONE, "needed ids not found - c2sid:%d target:%d", c2sid, target);
1079  nad_free(nad);
1080  free(tres);
1081  return 0;
1082  }
1083  jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target));
1084  snprintf(tres->c2s_id, sizeof(tres->c2s_id), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid));
1085  }
1086  tres->jid = jid;
1087  snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1088 
1089  if(sess->resources) {
1090  log_debug(ZONE, "expected packet from sm session %s, but got one from %.*s, ending sm session", sess->resources->sm_id, NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1091  } else {
1092  log_debug(ZONE, "no resource bound yet, but got packet from sm session %.*s, ending sm session", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1093  }
1094 
1095  /* end a session with the sm */
1096  sm_end(sess, tres);
1097 
1098  /* finished with the nad */
1099  nad_free(nad);
1100 
1101  /* free temp objects */
1102  jid_free(jid);
1103  free(tres);
1104 
1105  return 0;
1106  }
1107 
1108  /* session control packets */
1109  if(NAD_ENS(nad, 1) == ns && action >= 0) {
1110  /* end responses */
1111 
1112  /* !!! this "replaced" stuff is a hack - its really a subaction of "ended".
1113  * hurrah, another control protocol rewrite is needed :(
1114  */
1115 
1116  replaced = 0;
1117  if(NAD_AVAL_L(nad, action) == 8 && strncmp("replaced", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0)
1118  replaced = 1;
1119  if(sess->active &&
1120  (replaced || (NAD_AVAL_L(nad, action) == 5 && strncmp("ended", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0))) {
1121 
1122  sess->bound -= 1;
1123  /* no more resources bound? */
1124  if(sess->bound < 1){
1125  sess->active = 0;
1126 
1127  if(sess->s) {
1128  /* return the unbind result to the client */
1129  if(sess->result != NULL) {
1130  sx_nad_write(sess->s, sess->result);
1131  sess->result = NULL;
1132  }
1133 
1134  if(replaced)
1135  sx_error(sess->s, stream_err_CONFLICT, NULL);
1136 
1137  sx_close(sess->s);
1138 
1139  } else {
1140  // handle fake PBX sessions
1141  if(sess->result != NULL) {
1142  nad_free(sess->result);
1143  sess->result = NULL;
1144  }
1145  }
1146 
1147  nad_free(nad);
1148  return 0;
1149  }
1150 
1151  /* else remove the bound resource */
1152  if(bres == sess->resources) {
1153  sess->resources = bres->next;
1154  } else {
1155  for(ires = sess->resources; ires != NULL; ires = ires->next)
1156  if(ires->next == bres)
1157  break;
1158  assert(ires != NULL);
1159  ires->next = bres->next;
1160  }
1161 
1162  log_write(sess->c2s->log, LOG_NOTICE, "[%d] unbound: jid=%s", sess->s->tag, jid_full(bres->jid));
1163 
1164  jid_free(bres->jid);
1165  free(bres);
1166 
1167  /* and return the unbind result to the client */
1168  if(sess->result != NULL) {
1169  sx_nad_write(sess->s, sess->result);
1170  sess->result = NULL;
1171  }
1172 
1173  return 0;
1174  }
1175 
1176  id = nad_find_attr(nad, 1, -1, "id", NULL);
1177 
1178  /* make sure the id matches */
1179  if(id < 0 || bres->sm_request[0] == '\0' || strlen(bres->sm_request) != NAD_AVAL_L(nad, id) || strncmp(bres->sm_request, NAD_AVAL(nad, id), NAD_AVAL_L(nad, id)) != 0) {
1180  if(id >= 0) {
1181  log_debug(ZONE, "got a response with id %.*s, but we were expecting %s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id), bres->sm_request);
1182  } else {
1183  log_debug(ZONE, "got a response with no id, but we were expecting %s", bres->sm_request);
1184  }
1185 
1186  nad_free(nad);
1187  return 0;
1188  }
1189 
1190  /* failed requests */
1191  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1192  /* handled request */
1193  bres->sm_request[0] = '\0';
1194 
1195  /* we only care about failed start and create */
1196  if((NAD_AVAL_L(nad, action) == 5 && strncmp("start", NAD_AVAL(nad, action), 5) == 0) ||
1197  (NAD_AVAL_L(nad, action) == 6 && strncmp("create", NAD_AVAL(nad, action), 6) == 0)) {
1198 
1199  /* create failed, so we need to remove them from authreg */
1200  if(NAD_AVAL_L(nad, action) == 6 && sess->host->ar->delete_user != NULL) {
1201  if((sess->host->ar->delete_user)(sess->host->ar, sess, bres->jid->node, sess->host->realm) != 0)
1202  log_write(c2s->log, LOG_NOTICE, "[%d] user creation failed, and unable to delete user credentials: user=%s, realm=%s", sess->s->tag, bres->jid->node, sess->host->realm);
1203  else
1204  log_write(c2s->log, LOG_NOTICE, "[%d] user creation failed, so deleted user credentials: user=%s, realm=%s", sess->s->tag, bres->jid->node, sess->host->realm);
1205  }
1206 
1207  /* error the result and return it to the client */
1209  sess->result = NULL;
1210 
1211  /* remove the bound resource */
1212  if(bres == sess->resources) {
1213  sess->resources = bres->next;
1214  } else {
1215  for(ires = sess->resources; ires != NULL; ires = ires->next)
1216  if(ires->next == bres)
1217  break;
1218  assert(ires != NULL);
1219  ires->next = bres->next;
1220  }
1221 
1222  jid_free(bres->jid);
1223  free(bres);
1224 
1225  nad_free(nad);
1226  return 0;
1227  }
1228 
1229  log_debug(ZONE, "weird, got a failed session response, with a matching id, but the action is bogus *shrug*");
1230 
1231  nad_free(nad);
1232  return 0;
1233  }
1234 
1235  /* session started */
1236  if(NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) {
1237  /* handled request */
1238  bres->sm_request[0] = '\0';
1239 
1240  /* copy the sm id */
1241  if(smid >= 0)
1242  snprintf(bres->sm_id, sizeof(bres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1243 
1244  /* and remember the SM that services us */
1245  from = nad_find_attr(nad, 0, -1, "from", NULL);
1246 
1247 
1248  smcomp = malloc(NAD_AVAL_L(nad, from) + 1);
1249  snprintf(smcomp, NAD_AVAL_L(nad, from) + 1, "%.*s", NAD_AVAL_L(nad, from), NAD_AVAL(nad, from));
1250  sess->smcomp = smcomp;
1251 
1252  nad_free(nad);
1253 
1254  /* bring them online, old-skool */
1255  if(!sess->sasl_authd && sess->s) {
1256  sx_auth(sess->s, "traditional", jid_full(bres->jid));
1257  return 0;
1258  }
1259 
1260  if(sess->result) {
1261  /* return the auth result to the client */
1262  if(sess->s) sx_nad_write(sess->s, sess->result);
1263  /* or follow-up the session creation with cached presence packet */
1264  else sm_packet(sess, bres, sess->result);
1265  }
1266  sess->result = NULL;
1267 
1268  /* we're good to go */
1269  sess->active = 1;
1270 
1271  return 0;
1272  }
1273 
1274  /* handled request */
1275  bres->sm_request[0] = '\0';
1276 
1277  log_debug(ZONE, "unknown action %.*s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id));
1278 
1279  nad_free(nad);
1280 
1281  return 0;
1282  }
1283 
1284  /* client packets */
1285  if(NAD_NURI_L(nad, NAD_ENS(nad, 1)) == strlen(uri_CLIENT) && strncmp(uri_CLIENT, NAD_NURI(nad, NAD_ENS(nad, 1)), strlen(uri_CLIENT)) == 0) {
1286  if(!sess->active || !sess->s) {
1287  /* its a strange world .. */
1288  log_debug(ZONE, "Got packet for %s - dropping", !sess->s ? "session without stream (PBX pipe session?)" : "inactive session");
1289  nad_free(nad);
1290  return 0;
1291  }
1292 
1293  /* sm is bouncing something */
1294  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1295  /* there's really no graceful way to handle this */
1296  sx_error(s, stream_err_INTERNAL_SERVER_ERROR, "session manager failed control action");
1297  sx_close(s);
1298 
1299  nad_free(nad);
1300  return 0;
1301  }
1302 
1303  /* we're counting packets */
1304  sess->packet_count++;
1305  sess->c2s->packet_count++;
1306 
1307  /* remove sm specifics */
1308  nad_set_attr(nad, 1, ns, "c2s", NULL, 0);
1309  nad_set_attr(nad, 1, ns, "sm", NULL, 0);
1310 
1311  /* forget about the internal namespace too */
1312  if(nad->elems[1].ns == ns)
1313  nad->elems[1].ns = nad->nss[ns].next;
1314 
1315  else {
1316  for(scan = nad->elems[1].ns; nad->nss[scan].next != -1 && nad->nss[scan].next != ns; scan = nad->nss[scan].next);
1317 
1318  /* got it */
1319  if(nad->nss[scan].next != -1)
1320  nad->nss[scan].next = nad->nss[ns].next;
1321  }
1322 
1323  sx_nad_write_elem(sess->s, nad, 1);
1324 
1325  return 0;
1326  }
1327 
1328  /* its something else */
1329  log_debug(ZONE, "unknown packet, dropping");
1330 
1331  nad_free(nad);
1332  return 0;
1333 
1334  case event_CLOSED:
1335  mio_close(c2s->mio, c2s->fd);
1336  c2s->fd = NULL;
1337  return -1;
1338  }
1339 
1340  return 0;
1341 }
1342 
1343 int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
1344  c2s_t c2s = (c2s_t) arg;
1345  int nbytes;
1346 
1347  switch(a) {
1348  case action_READ:
1349  log_debug(ZONE, "read action on fd %d", fd->fd);
1350 
1351  ioctl(fd->fd, FIONREAD, &nbytes);
1352  if(nbytes == 0) {
1353  sx_kill(c2s->router);
1354  return 0;
1355  }
1356 
1357  return sx_can_read(c2s->router);
1358 
1359  case action_WRITE:
1360  log_debug(ZONE, "write action on fd %d", fd->fd);
1361  return sx_can_write(c2s->router);
1362 
1363  case action_CLOSE:
1364  log_debug(ZONE, "close action on fd %d", fd->fd);
1365  log_write(c2s->log, LOG_NOTICE, "connection to router closed");
1366 
1367  c2s_lost_router = 1;
1368 
1369  /* we're offline */
1370  c2s->online = 0;
1371 
1372  break;
1373 
1374  case action_ACCEPT:
1375  break;
1376  }
1377 
1378  return 0;
1379 }
const char * ip
Definition: sx.h:262
struct bres_st * bres_t
Definition: c2s.h:54
bres_t resources
Definition: c2s.h:103
struct nad_elem_st * elems
Definition: nad.h:95
Definition: nad.h:93
struct sess_st * sess_t
Definition: c2s.h:55
C2S_API void sm_end(sess_t sess, bres_t res)
Definition: sm.c:72
nad_t nad_new(void)
create a new nad
Definition: nad.c:125
Definition: sx.h:113
int nad_append_attr(nad_t nad, int ns, const char *name, const char *val)
attach new attr to the last elem
Definition: nad.c:745
struct stream_redirect_st * stream_redirect_t
_sx_state_t state
Definition: sx.h:319
#define NAD_CDATA_L(N, E)
Definition: nad.h:186
mio_fd_t fd
Definition: c2s.h:77
char sm_request[41]
this holds the id of the current pending SM request
Definition: c2s.h:65
unsigned int flags
Definition: sx.h:276
#define sx_nad_write(s, nad)
Definition: sx.h:167
void * pmalloc(pool_t p, int size)
Definition: pool.c:141
void sx_nad_write_elem(sx_t s, nad_t nad, int elem)
app version
Definition: io.c:449
struct host_st * host_t
Definition: c2s.h:52
Definition: sx.h:59
const char * jid_user(jid_t jid)
expand and return the user
Definition: jid.c:338
int started
this is true if we&#39;ve connected to the router at least once
Definition: c2s.h:305
const char * req_to
Definition: sx.h:282
unsigned int packet_count
Definition: c2s.h:98
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:346
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
int nad_find_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val)
get a matching attr on this elem, both name and optional val
Definition: nad.c:237
access_t access
access controls
Definition: c2s.h:296
void rate_add(rate_t rt, int count)
Add a number of events to the counter.
Definition: rate.c:48
static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
Definition: c2s.c:25
void nad_set_attr(nad_t nad, unsigned int elem, int ns, const char *name, const char *val, int vallen)
create, update, or zap any matching attr on this elem
Definition: nad.c:407
Definition: sx.h:65
void nad_append_cdata(nad_t nad, const char *cdata, int len, int depth)
append new cdata to the last elem
Definition: nad.c:753
xht conn_rates
Definition: c2s.h:280
int compression
enable Stream Compression
Definition: c2s.h:255
void log_write(log_t log, int level, const char *msgfmt,...)
Definition: log.c:104
int retry_left
Definition: c2s.h:211
#define stream_err_INTERNAL_SERVER_ERROR
Definition: sx.h:131
int conn_rate_seconds
Definition: c2s.h:277
rate_t rate_new(int total, int seconds, int wait)
Definition: rate.c:25
error info for event_ERROR
Definition: sx.h:99
int rbytesmax
Definition: sx.h:316
C2S_API void sm_packet(sess_t sess, bres_t res, nad_t nad)
Definition: sm.c:86
sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg)
if you change these, reflect your changes in the table in error.c
Definition: sx.c:23
#define MIO_STRERROR(e)
Definition: mio.h:170
int tag
Definition: sx.h:258
int sx_can_write(sx_t s)
Definition: io.c:347
#define uri_TLS
Definition: uri.h:40
list of resources bound to session
Definition: c2s.h:59
int nad_add_namespace(nad_t nad, const char *uri, const char *prefix)
bring a new namespace into scope
Definition: nad.c:778
void nad_print(nad_t nad, unsigned int elem, const char **xml, int *len)
create a string representation of the given element (and children), point references to it ...
Definition: nad.c:1208
nad_t result
Definition: c2s.h:108
void sx_server_init(sx_t s, unsigned int flags)
Definition: server.c:248
const char * id
our id (hostname) with the router
Definition: c2s.h:159
#define NAD_ENAME(N, E)
Definition: nad.h:183
mio_action_t
these are the actions and a handler type assigned by the applicaiton using mio
Definition: mio.h:106
char * resource
Definition: jid.h:46
Definition: mio.h:109
int nad_append_elem(nad_t nad, int ns, const char *name, int depth)
create a new elem on the list
Definition: nad.c:711
void nad_free(nad_t nad)
free that nad
Definition: nad.c:180
int stanza_size_limit
maximum stanza size
Definition: c2s.h:293
int xhash_iter_next(xht h)
Definition: xhash.c:320
void jid_random_part(jid_t jid, jid_part_t part)
create random resource
Definition: jid.c:491
const char * auth_method
Definition: sx.h:333
sx_t router
router&#39;s conn
Definition: c2s.h:183
#define uri_BIND
Definition: uri.h:42
#define SX_COMPRESS_OFFER
Definition: plugins.h:32
jid_t jid
full bound jid
Definition: c2s.h:61
Definition: sx.h:60
time_t last_activity
Definition: c2s.h:97
mio_fd_t server_fd
listening sockets
Definition: c2s.h:187
void rate_free(rate_t rt)
Definition: rate.c:36
const char * router_pemfile
Definition: c2s.h:166
#define mio_read(m, fd)
process read events for this fd
Definition: mio.h:161
sx_t s
Definition: c2s.h:86
int nad_find_namespace(nad_t nad, unsigned int elem, const char *uri, const char *prefix)
get a matching ns on this elem, both uri and optional prefix
Definition: nad.c:264
const char * ip
Definition: c2s.h:83
int stanza_rate_log
Definition: c2s.h:95
const char * local_ip
ip to listen on
Definition: c2s.h:214
int authreg_process(c2s_t c2s, sess_t sess, nad_t nad)
processor for iq:auth and iq:register packets return 0 if handled, 1 if not handled ...
Definition: authreg.c:680
#define MIO_ERROR
all MIO related routines should use those for error reporting
Definition: mio.h:168
const char * router_private_key_password
Definition: c2s.h:168
#define MIO_WOULDBLOCK
Definition: mio.h:171
void pool_cleanup(pool_t p, pool_cleanup_t f, void *arg)
public cleanup utils, insert in a way that they are run FIFO, before mem frees
Definition: pool.c:251
int sx_can_read(sx_t s)
we can read
Definition: io.c:196
struct rate_st * rate_t
sx_plugin_t sx_ssl
Definition: c2s.h:179
#define SX_ERR_AUTH
Definition: sx.h:95
void(* sess_end)(authreg_t ar, sess_t sess)
called prior to session being closed, to cleanup session specific private data
Definition: c2s.h:364
jid_t jid_reset_components(jid_t jid, const char *node, const char *domain, const char *resource)
build a jid from components
Definition: jid.c:281
mio_t mio
mio context
Definition: c2s.h:172
#define stanza_err_UNKNOWN_SENDER
Definition: util.h:389
holds the state for a single stream
Definition: sx.h:253
int stanza_rate_wait
Definition: c2s.h:290
char * data
Definition: sx.h:114
int port
Definition: c2s.h:84
int j_inet_getport(struct sockaddr_storage *sa)
get the port number out of a struct sockaddr_storage
Definition: inaddr.c:148
const char * to_address
Definition: c2s.h:412
void ** val
Definition: c2s.h:404
const char * smcomp
Definition: c2s.h:81
struct c2s_st * c2s_t
Definition: c2s.h:53
struct nad_ns_st * nss
Definition: nad.h:97
#define NAD_ENAME_L(N, E)
Definition: nad.h:184
void jqueue_push(jqueue_t q, void *data, int priority)
Definition: jqueue.c:44
#define NAD_NURI_L(N, NS)
Definition: nad.h:192
const char * router_pass
Definition: c2s.h:165
void jid_free(jid_t jid)
free a jid
Definition: jid.c:286
const char * realm
our realm (SASL)
Definition: c2s.h:126
int bound
Definition: c2s.h:101
void xhash_put(xht h, const char *key, void *val)
Definition: xhash.c:163
#define SX_SSL_STARTTLS_OFFER
Definition: plugins.h:26
sess_t * sess_val
Definition: c2s.h:406
authreg_t ar
Definition: c2s.h:148
#define stanza_err_BAD_REQUEST
Definition: util.h:367
char * domain
Definition: jid.h:45
host_t host
host this session belongs to
Definition: c2s.h:89
#define mio_listen(m, port, sourceip, app, arg)
for creating a new listen socket in this mio (returns new fd or <0)
Definition: mio.h:140
const char * generic
Definition: sx.h:101
int code
Definition: sx.h:100
Definition: jid.h:42
int byte_rate_seconds
Definition: c2s.h:284
int local_port
unencrypted port
Definition: c2s.h:217
int ecur
Definition: nad.h:105
Definition: c2s.h:124
void sx_error_extended(sx_t s, int err, const char *content)
Definition: error.c:140
#define stream_err_HOST_GONE
Definition: sx.h:128
xht hosts
hosts mapping
Definition: c2s.h:311
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
Definition: xhash.c:374
#define NAD_AVAL_L(N, A)
Definition: nad.h:190
const char * host_pemfile
starttls pemfile
Definition: c2s.h:129
int conn_rate_total
connection rates
Definition: c2s.h:276
int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
Definition: c2s.c:681
void sx_close(sx_t s)
Definition: io.c:512
static int _c2s_client_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
Definition: c2s.c:505
int byte_rate_wait
Definition: c2s.h:285
void xhash_zap(xht h, const char *key)
Definition: xhash.c:235
const char * auth_id
Definition: sx.h:334
#define log_debug(...)
Definition: log.h:65
void * authreg_private
Definition: c2s.h:116
sx_env_t sx_env
sx environment
Definition: c2s.h:178
#define SX_WEBSOCKET_WRAPPER
Definition: plugins.h:34
#define SX_SSL_STARTTLS_REQUIRE
Definition: plugins.h:27
int rate_check(rate_t rt)
Definition: rate.c:78
char c2s_id[44]
session id for this jid for us and them
Definition: c2s.h:63
#define uri_STREAMS
Definition: uri.h:34
nad_t stanza_error(nad_t nad, int elem, int err)
error the packet
Definition: stanza.c:52
int stanza_rate_seconds
Definition: c2s.h:289
#define uri_CLIENT
Definition: uri.h:35
xht sm_avail
availability of sms that we are servicing
Definition: c2s.h:315
#define NAD_AVAL(N, A)
Definition: nad.h:189
struct _sx_buf_st * sx_buf_t
utility: buffer
Definition: sx.h:112
Definition: c2s.h:157
C2S_API void sm_start(sess_t sess, bres_t res)
Definition: sm.c:66
static int _c2s_client_accept_check(c2s_t c2s, mio_fd_t fd, const char *ip)
Definition: c2s.c:478
host_t vhost
Definition: c2s.h:312
int ns
Definition: nad.h:75
void sx_error(sx_t s, int err, const char *text)
Definition: error.c:94
xht stream_redirects
stream redirection (see-other-host) on session connect
Definition: c2s.h:249
int conn_rate_wait
Definition: c2s.h:278
#define SX_SASL_OFFER
Definition: plugins.h:29
#define stream_err_POLICY_VIOLATION
Definition: sx.h:137
#define stanza_err_ITEM_NOT_FOUND
Definition: util.h:373
JABBERD2_API int sx_sasl_auth(sx_plugin_t p, sx_t s, const char *appname, const char *mech, const char *user, const char *pass)
trigger for client auth
Definition: sasl.c:915
int retry_lost
Definition: c2s.h:209
sig_atomic_t c2s_lost_router
Definition: main.c:28
jqueue_t dead_sess
list of sess on the way out
Definition: c2s.h:302
There is one instance of this struct per user who is logged in to this c2s instance.
Definition: c2s.h:74
#define mio_app(m, fd, app, arg)
re-set the app handler
Definition: mio.h:152
int ssf
Definition: sx.h:343
int nad_find_elem(nad_t nad, unsigned int elem, int ns, const char *name, int depth)
locate the next elem at a given depth with an optional matching name
Definition: nad.c:206
mio_fd_t fd
Definition: c2s.h:184
const char * specific
Definition: sx.h:102
C2S_API void c2s_pbx_init(c2s_t c2s)
Definition: pbx.c:120
int xhash_iter_first(xht h)
iteration
Definition: xhash.c:311
const char * to_port
Definition: c2s.h:413
int fd
Definition: mio.h:102
long long int packet_count
packet counter
Definition: c2s.h:204
unsigned int len
Definition: sx.h:115
int rate_log
Definition: c2s.h:92
xht sessions
sessions
Definition: c2s.h:175
rate_t rate
Definition: c2s.h:91
pool_t xhash_pool(xht h)
get our pool
Definition: xhash.c:305
int access_check(access_t access, const char *ip)
Definition: access.c:204
int rate_left(rate_t rt)
Definition: rate.c:69
char * pstrdup(pool_t p, const char *src)
XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is wit...
Definition: pool.c:191
rate_t stanza_rate
Definition: c2s.h:94
Definition: mio.h:100
#define NAD_CDATA(N, E)
Definition: nad.h:185
void sx_kill(sx_t s)
Definition: io.c:527
Definition: util.h:258
int tbytes
Definition: sx.h:313
int local_ssl_port
encrypted port
Definition: c2s.h:220
void * xhash_get(xht h, const char *key)
Definition: xhash.c:184
#define uri_COMPONENT
Definition: uri.h:52
#define mio_close(m, fd)
request that mio close this fd
Definition: mio.h:155
#define SX_SSL_WRAPPER
sx stream flags
Definition: plugins.h:25
#define stream_err_NOT_AUTHORIZED
Definition: sx.h:136
sx_plugin_t sx_sasl
Definition: c2s.h:180
#define mio_write(m, fd)
mio should try the write action on this fd now
Definition: mio.h:158
int port
Definition: sx.h:266
#define ZONE
Definition: mio_impl.h:76
session packet handling
Definition: c2s.h:402
#define NAD_NURI(N, NS)
Definition: nad.h:191
sx_event_t
things that can happen
Definition: sx.h:56
int next
Definition: nad.h:90
c2s_t c2s
Definition: c2s.h:75
jqueue_t dead
list of sx_t on the way out
Definition: c2s.h:299
Definition: sx.h:74
#define uri_SESSION
Definition: uri.h:53
log_t log
logging
Definition: c2s.h:196
const char * pbx_pipe
PBX integration named pipe.
Definition: c2s.h:244
#define stream_err_CONFLICT
Definition: sx.h:126
#define stream_err_HOST_UNKNOWN
Definition: sx.h:129
Definition: sx.h:62
const char * router_user
Definition: c2s.h:164
void sx_auth(sx_t s, const char *auth_method, const char *auth_id)
force advance into auth state
Definition: sx.c:141
char sm_id[41]
Definition: c2s.h:63
#define stream_err_SEE_OTHER_HOST
Definition: sx.h:141
int host_require_starttls
require starttls
Definition: c2s.h:141
char skey[44]
Definition: c2s.h:79
struct nad_st * nad_t
int online
true if we&#39;re bound in the router
Definition: c2s.h:308
#define stanza_err_INTERNAL_SERVER_ERROR
Definition: util.h:372
int sasl_authd
Definition: c2s.h:110
int active
Definition: c2s.h:105
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
Definition: ssl.c:1117
char * node
Definition: jid.h:44
void(* free)(authreg_t ar)
called prior to authreg shutdown
Definition: c2s.h:367
int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
Definition: c2s.c:1343
#define NAD_ENS(N, E)
Definition: nad.h:196
int stanza_rate_total
stanza rates
Definition: c2s.h:288
const char * local_pemfile
encrypted port pemfile
Definition: c2s.h:223
int(* delete_user)(authreg_t ar, sess_t sess, const char *username, const char *realm)
Definition: c2s.h:361
static void _c2s_component_presence(c2s_t c2s, nad_t nad)
Definition: c2s.c:629
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:292
bres_t next
Definition: c2s.h:67
char * _sx_flags(sx_t s)
show sx flags as string - for logging
Definition: sx.c:349
int byte_rate_total
byte rates (karma)
Definition: c2s.h:283