jabberd2  2.3.4
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->rbytes_total);
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  getpeername(fd->fd, (struct sockaddr *) &sa, &namelen);
566  port = j_inet_getport(&sa);
567 
568  log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connect", fd->fd, (char *) data, port);
569 
570  if(_c2s_client_accept_check(c2s, fd, (char *) data) != 0)
571  return 1;
572 
573  sess = (sess_t) calloc(1, sizeof(struct sess_st));
574 
575  sess->c2s = c2s;
576 
577  sess->fd = fd;
578 
579  sess->ip = strdup((char *) data);
580  sess->port = port;
581 
582  /* they did something */
583  sess->last_activity = time(NULL);
584 
585  sess->s = sx_new(c2s->sx_env, fd->fd, _c2s_client_sx_callback, (void *) sess);
586  mio_app(m, fd, _c2s_client_mio_callback, (void *) sess);
587 
588  if(c2s->stanza_size_limit != 0)
589  sess->s->rbytesmax = c2s->stanza_size_limit;
590 
591  if(c2s->byte_rate_total != 0)
593 
594  if(c2s->stanza_rate_total != 0)
596 
597  /* give IP to SX */
598  sess->s->ip = sess->ip;
599  sess->s->port = sess->port;
600 
601  /* find out which port this is */
602  getsockname(fd->fd, (struct sockaddr *) &sa, &namelen);
603  port = j_inet_getport(&sa);
604 
605  /* remember it */
606  sprintf(sess->skey, "%d", fd->fd);
607  xhash_put(c2s->sessions, sess->skey, (void *) sess);
608 
609  flags = SX_SASL_OFFER;
610 #ifdef HAVE_SSL
611  /* go ssl wrappermode if they're on the ssl port */
612  if(port == c2s->local_ssl_port)
613  flags |= SX_SSL_WRAPPER;
614 #endif
615 #ifdef HAVE_LIBZ
616  if(c2s->compression && !(sess->s->flags & SX_WEBSOCKET_WRAPPER))
617  flags |= SX_COMPRESS_OFFER;
618 #endif
619  sx_server_init(sess->s, flags);
620 
621  break;
622  }
623 
624  return 0;
625 }
626 
627 static void _c2s_component_presence(c2s_t c2s, nad_t nad) {
628  int attr;
629  char from[1024];
630  sess_t sess;
631  union xhashv xhv;
632 
633  if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) < 0) {
634  nad_free(nad);
635  return;
636  }
637 
638  strncpy(from, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));
639  from[NAD_AVAL_L(nad, attr)] = '\0';
640 
641  if(nad_find_attr(nad, 0, -1, "type", NULL) < 0) {
642  log_debug(ZONE, "component available from '%s'", from);
643 
644  log_debug(ZONE, "sm for serviced domain '%s' online", from);
645 
646  xhash_put(c2s->sm_avail, pstrdup(xhash_pool(c2s->sm_avail), from), (void *) 1);
647 
648  nad_free(nad);
649  return;
650  }
651 
652  if(nad_find_attr(nad, 0, -1, "type", "unavailable") < 0) {
653  nad_free(nad);
654  return;
655  }
656 
657  log_debug(ZONE, "component unavailable from '%s'", from);
658 
659  if(xhash_get(c2s->sm_avail, from) != NULL) {
660  log_debug(ZONE, "sm for serviced domain '%s' offline", from);
661 
662  if(xhash_iter_first(c2s->sessions))
663  do {
664  xhv.sess_val = &sess;
665  xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val);
666 
667  if(sess->resources != NULL && strcmp(sess->resources->jid->domain, from) == 0) {
668  log_debug(ZONE, "killing session %s", jid_user(sess->resources->jid));
669 
670  sess->active = 0;
671  if(sess->s) sx_close(sess->s);
672  }
673  } while(xhash_iter_next(c2s->sessions));
674 
675  xhash_zap(c2s->sm_avail, from);
676  }
677 }
678 
679 int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
680  c2s_t c2s = (c2s_t) arg;
681  sx_buf_t buf = (sx_buf_t) data;
682  sx_error_t *sxe;
683  nad_t nad;
684  int len, elem, from, c2sid, smid, action, id, ns, attr, scan, replaced;
685  char skey[44];
686  sess_t sess;
687  bres_t bres, ires;
688  char *smcomp;
689 
690  switch(e) {
691  case event_WANT_READ:
692  log_debug(ZONE, "want read");
693  mio_read(c2s->mio, c2s->fd);
694  break;
695 
696  case event_WANT_WRITE:
697  log_debug(ZONE, "want write");
698  mio_write(c2s->mio, c2s->fd);
699  break;
700 
701  case event_READ:
702  log_debug(ZONE, "reading from %d", c2s->fd->fd);
703 
704  /* do the read */
705  len = recv(c2s->fd->fd, buf->data, buf->len, 0);
706 
707  if(len < 0) {
708  if(MIO_WOULDBLOCK) {
709  buf->len = 0;
710  return 0;
711  }
712 
713  log_write(c2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
714 
715  sx_kill(s);
716 
717  return -1;
718  }
719 
720  else if(len == 0) {
721  /* they went away */
722  sx_kill(s);
723 
724  return -1;
725  }
726 
727  log_debug(ZONE, "read %d bytes", len);
728 
729  buf->len = len;
730 
731  return len;
732 
733  case event_WRITE:
734  log_debug(ZONE, "writing to %d", c2s->fd->fd);
735 
736  len = send(c2s->fd->fd, buf->data, buf->len, 0);
737  if(len >= 0) {
738  log_debug(ZONE, "%d bytes written", len);
739  return len;
740  }
741 
742  if(MIO_WOULDBLOCK)
743  return 0;
744 
745  log_write(c2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
746 
747  sx_kill(s);
748 
749  return -1;
750 
751  case event_ERROR:
752  sxe = (sx_error_t *) data;
753  log_write(c2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific);
754 
755  if(sxe->code == SX_ERR_AUTH)
756  sx_close(s);
757 
758  break;
759 
760  case event_STREAM:
761  break;
762 
763  case event_OPEN:
764  log_write(c2s->log, LOG_NOTICE, "connection to router established");
765 
766  /* set connection attempts counter */
767  c2s->retry_left = c2s->retry_lost;
768 
769  nad = nad_new();
770  ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
771  nad_append_elem(nad, ns, "bind", 0);
772  nad_append_attr(nad, -1, "name", c2s->id);
773 
774  log_debug(ZONE, "requesting component bind for '%s'", c2s->id);
775 
776  sx_nad_write(c2s->router, nad);
777 
778  return 0;
779 
780  case event_PACKET:
781  nad = (nad_t) data;
782 
783  /* drop unqualified packets */
784  if(NAD_ENS(nad, 0) < 0) {
785  nad_free(nad);
786  return 0;
787  }
788 
789  /* watch for the features packet */
790  if(s->state == state_STREAM) {
791  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) {
792  log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping");
793  nad_free(nad);
794  return 0;
795  }
796 
797 #ifdef HAVE_SSL
798  /* starttls if we can */
799  if(c2s->sx_ssl != NULL && c2s->router_pemfile != NULL && s->ssf == 0) {
800  ns = nad_find_scoped_namespace(nad, uri_TLS, NULL);
801  if(ns >= 0) {
802  elem = nad_find_elem(nad, 0, ns, "starttls", 1);
803  if(elem >= 0) {
805  nad_free(nad);
806  return 0;
807  }
808  log_write(c2s->log, LOG_ERR, "unable to establish encrypted session with router");
809  }
810  }
811  }
812 #endif
813 
814  /* !!! pull the list of mechanisms, and choose the best one.
815  * if there isn't an appropriate one, error and bail */
816 
817  /* authenticate */
818  sx_sasl_auth(c2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", c2s->router_user, c2s->router_pass);
819 
820  nad_free(nad);
821  return 0;
822  }
823 
824  /* watch for the bind response */
825  if(s->state == state_OPEN && !c2s->online) {
826  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) {
827  log_debug(ZONE, "got a packet from router, but we're not online, dropping");
828  nad_free(nad);
829  return 0;
830  }
831 
832  /* catch errors */
833  attr = nad_find_attr(nad, 0, -1, "error", NULL);
834  if(attr >= 0) {
835  log_write(c2s->log, LOG_ERR, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
836  exit(1);
837  }
838 
839  log_debug(ZONE, "coming online");
840 
841  /* if we're coming online for the first time, setup listening sockets */
842 #ifdef HAVE_SSL
843  if(c2s->server_fd == 0 && c2s->server_ssl_fd == 0) {
844 #else
845  if(c2s->server_fd == 0) {
846 #endif
847  if(c2s->local_port != 0) {
848  c2s->server_fd = mio_listen(c2s->mio, c2s->local_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s);
849  if(c2s->server_fd == NULL)
850  log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_port);
851  else
852  log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", c2s->local_ip, c2s->local_port);
853  } else
854  c2s->server_fd = NULL;
855 
856 #ifdef HAVE_SSL
857  if(c2s->local_ssl_port != 0 && c2s->local_pemfile != NULL) {
858  c2s->server_ssl_fd = mio_listen(c2s->mio, c2s->local_ssl_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s);
859  if(c2s->server_ssl_fd == NULL)
860  log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_ssl_port);
861  else
862  log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for SSL connections", c2s->local_ip, c2s->local_ssl_port);
863  } else
864  c2s->server_ssl_fd = NULL;
865 #endif
866  }
867 
868 #ifdef HAVE_SSL
869  if(c2s->server_fd == NULL && c2s->server_ssl_fd == NULL && c2s->pbx_pipe == NULL) {
870  log_write(c2s->log, LOG_ERR, "both normal and SSL ports are disabled, nothing to do!");
871 #else
872  if(c2s->server_fd == NULL && c2s->pbx_pipe == NULL) {
873  log_write(c2s->log, LOG_ERR, "server port is disabled, nothing to do!");
874 #endif
875  exit(1);
876  }
877 
878  /* open PBX integration FIFO */
879  if(c2s->pbx_pipe != NULL)
880  c2s_pbx_init(c2s);
881 
882  /* we're online */
883  c2s->online = c2s->started = 1;
884  log_write(c2s->log, LOG_NOTICE, "ready for connections", c2s->id);
885 
886  nad_free(nad);
887  return 0;
888  }
889 
890  /* need component packets */
891  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) {
892  log_debug(ZONE, "wanted component packet, dropping");
893  nad_free(nad);
894  return 0;
895  }
896 
897  /* component presence */
898  if(NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) {
899  _c2s_component_presence(c2s, nad);
900  return 0;
901  }
902 
903  /* we want route */
904  if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) {
905  log_debug(ZONE, "wanted {component}route, dropping");
906  nad_free(nad);
907  return 0;
908  }
909 
910  /* only handle unicasts */
911  if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) {
912  log_debug(ZONE, "non-unicast packet, dropping");
913  nad_free(nad);
914  return 0;
915  }
916 
917  /* need some payload */
918  if(nad->ecur == 1) {
919  log_debug(ZONE, "no route payload, dropping");
920  nad_free(nad);
921  return 0;
922  }
923 
924  ns = nad_find_namespace(nad, 1, uri_SESSION, NULL);
925  if(ns < 0) {
926  log_debug(ZONE, "not a c2s packet, dropping");
927  nad_free(nad);
928  return 0;
929  }
930 
931  /* figure out the session */
932  c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL);
933  if(c2sid < 0) {
934  log_debug(ZONE, "no c2s id on payload, dropping");
935  nad_free(nad);
936  return 0;
937  }
938  snprintf(skey, sizeof(skey), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid));
939 
940  /* find the session, quietly drop if we don't have it */
941  sess = xhash_get(c2s->sessions, skey);
942  if(sess == NULL) {
943  /* if we get this, the SM probably thinks the session is still active
944  * so we need to tell SM to free it up */
945  log_debug(ZONE, "no session for %s", skey);
946 
947  /* check if it's a started action; otherwise we could end up in an infinite loop
948  * trying to tell SM to close in response to errors */
949  action = nad_find_attr(nad, 1, -1, "action", NULL);
950  if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) {
951  int target;
952  bres_t tres;
953  sess_t tsess;
954 
955  log_write(c2s->log, LOG_NOTICE, "session %s does not exist; telling sm to close", skey);
956 
957  /* we don't have a session and we don't have a resource; we need to forge them both
958  * to get SM to close stuff */
959  target = nad_find_attr(nad, 1, -1, "target", NULL);
960  smid = nad_find_attr(nad, 1, ns, "sm", NULL);
961  if(target < 0 || smid < 0) {
962  const char *buf;
963  int len;
964  nad_print(nad, 0, &buf, &len);
965  log_write(c2s->log, LOG_NOTICE, "sm sent an invalid start packet: %.*s", len, buf );
966  nad_free(nad);
967  return 0;
968  }
969 
970  /* build temporary resource to close session for */
971  tres = NULL;
972  tres = (bres_t) calloc(1, sizeof(struct bres_st));
973  tres->jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target));
974 
975  strncpy(tres->c2s_id, skey, sizeof(tres->c2s_id));
976  snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
977 
978  /* make a temporary session */
979  tsess = (sess_t) calloc(1, sizeof(struct sess_st));
980  tsess->c2s = c2s;
981  tsess->result = nad_new();
982  strncpy(tsess->skey, skey, sizeof(tsess->skey));
983 
984  /* end a session with the sm */
985  sm_end(tsess, tres);
986 
987  /* free our temporary messes */
988  nad_free(tsess->result);
989  jid_free(tres->jid); //TODO will this crash?
990  free(tsess);
991  free(tres);
992  }
993 
994  nad_free(nad);
995  return 0;
996  }
997 
998  /* if they're pre-stream, then this is leftovers from a previous session */
999  if(sess->s && sess->s->state < state_STREAM) {
1000  log_debug(ZONE, "session %s is pre-stream", skey);
1001 
1002  nad_free(nad);
1003  return 0;
1004  }
1005 
1006  /* check the sm session id if they gave us one */
1007  smid = nad_find_attr(nad, 1, ns, "sm", NULL);
1008 
1009  /* get the action attribute */
1010  action = nad_find_attr(nad, 1, -1, "action", NULL);
1011 
1012  /* first user created packets - these are out of session */
1013  if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("created", NAD_AVAL(nad, action), 7) == 0) {
1014 
1015  nad_free(nad);
1016 
1017  if(sess->result) {
1018  /* return the result to the client */
1019  sx_nad_write(sess->s, sess->result);
1020  sess->result = NULL;
1021  } else {
1022  log_write(sess->c2s->log, LOG_WARNING, "user created for session %s which is already gone", skey);
1023  }
1024 
1025  return 0;
1026  }
1027 
1028  /* route errors */
1029  if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) {
1030  log_debug(ZONE, "routing error");
1031 
1032  if(sess->s) {
1033  sx_error(sess->s, stream_err_INTERNAL_SERVER_ERROR, "internal server error");
1034  sx_close(sess->s);
1035  }
1036 
1037  nad_free(nad);
1038  return 0;
1039  }
1040 
1041  /* all other packets need to contain an sm ID */
1042  if (smid < 0) {
1043  log_debug(ZONE, "received packet from sm without an sm ID, dropping");
1044  nad_free(nad);
1045  return 0;
1046  }
1047 
1048  /* find resource that we got packet for */
1049  bres = NULL;
1050  if(smid >= 0)
1051  for(bres = sess->resources; bres != NULL; bres = bres->next){
1052  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))
1053  break;
1054  }
1055  if(bres == NULL) {
1056  jid_t jid = NULL;
1057  bres_t tres = NULL;
1058 
1059  /* if it's a failure, just drop it */
1060  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1061  nad_free(nad);
1062  return 0;
1063  }
1064 
1065  /* build temporary resource to close session for */
1066  tres = (bres_t) calloc(1, sizeof(struct bres_st));
1067  if(sess->s) {
1068  jid = jid_new(sess->s->auth_id, -1);
1069  sprintf(tres->c2s_id, "%d", sess->s->tag);
1070  }
1071  else {
1072  /* does not have SX - extract values from route packet */
1073  int c2sid, target;
1074  c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL);
1075  target = nad_find_attr(nad, 1, -1, "target", NULL);
1076  if(c2sid < 0 || target < 0) {
1077  log_debug(ZONE, "needed ids not found - c2sid:%d target:%d", c2sid, target);
1078  nad_free(nad);
1079  free(tres);
1080  return 0;
1081  }
1082  jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target));
1083  snprintf(tres->c2s_id, sizeof(tres->c2s_id), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid));
1084  }
1085  tres->jid = jid;
1086  snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1087 
1088  if(sess->resources) {
1089  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));
1090  } else {
1091  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));
1092  }
1093 
1094  /* end a session with the sm */
1095  sm_end(sess, tres);
1096 
1097  /* finished with the nad */
1098  nad_free(nad);
1099 
1100  /* free temp objects */
1101  jid_free(jid);
1102  free(tres);
1103 
1104  return 0;
1105  }
1106 
1107  /* session control packets */
1108  if(NAD_ENS(nad, 1) == ns && action >= 0) {
1109  /* end responses */
1110 
1111  /* !!! this "replaced" stuff is a hack - its really a subaction of "ended".
1112  * hurrah, another control protocol rewrite is needed :(
1113  */
1114 
1115  replaced = 0;
1116  if(NAD_AVAL_L(nad, action) == 8 && strncmp("replaced", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0)
1117  replaced = 1;
1118  if(sess->active &&
1119  (replaced || (NAD_AVAL_L(nad, action) == 5 && strncmp("ended", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0))) {
1120 
1121  sess->bound -= 1;
1122  /* no more resources bound? */
1123  if(sess->bound < 1){
1124  sess->active = 0;
1125 
1126  if(sess->s) {
1127  /* return the unbind result to the client */
1128  if(sess->result != NULL) {
1129  sx_nad_write(sess->s, sess->result);
1130  sess->result = NULL;
1131  }
1132 
1133  if(replaced)
1134  sx_error(sess->s, stream_err_CONFLICT, NULL);
1135 
1136  sx_close(sess->s);
1137 
1138  } else {
1139  // handle fake PBX sessions
1140  if(sess->result != NULL) {
1141  nad_free(sess->result);
1142  sess->result = NULL;
1143  }
1144  }
1145 
1146  nad_free(nad);
1147  return 0;
1148  }
1149 
1150  /* else remove the bound resource */
1151  if(bres == sess->resources) {
1152  sess->resources = bres->next;
1153  } else {
1154  for(ires = sess->resources; ires != NULL; ires = ires->next)
1155  if(ires->next == bres)
1156  break;
1157  assert(ires != NULL);
1158  ires->next = bres->next;
1159  }
1160 
1161  log_write(sess->c2s->log, LOG_NOTICE, "[%d] unbound: jid=%s", sess->s->tag, jid_full(bres->jid));
1162 
1163  jid_free(bres->jid);
1164  free(bres);
1165 
1166  /* and return the unbind result to the client */
1167  if(sess->result != NULL) {
1168  sx_nad_write(sess->s, sess->result);
1169  sess->result = NULL;
1170  }
1171 
1172  return 0;
1173  }
1174 
1175  id = nad_find_attr(nad, 1, -1, "id", NULL);
1176 
1177  /* make sure the id matches */
1178  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) {
1179  if(id >= 0) {
1180  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);
1181  } else {
1182  log_debug(ZONE, "got a response with no id, but we were expecting %s", bres->sm_request);
1183  }
1184 
1185  nad_free(nad);
1186  return 0;
1187  }
1188 
1189  /* failed requests */
1190  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1191  /* handled request */
1192  bres->sm_request[0] = '\0';
1193 
1194  /* we only care about failed start and create */
1195  if((NAD_AVAL_L(nad, action) == 5 && strncmp("start", NAD_AVAL(nad, action), 5) == 0) ||
1196  (NAD_AVAL_L(nad, action) == 6 && strncmp("create", NAD_AVAL(nad, action), 6) == 0)) {
1197 
1198  /* create failed, so we need to remove them from authreg */
1199  if(NAD_AVAL_L(nad, action) == 6 && sess->host->ar->delete_user != NULL) {
1200  if((sess->host->ar->delete_user)(sess->host->ar, sess, bres->jid->node, sess->host->realm) != 0)
1201  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);
1202  else
1203  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);
1204  }
1205 
1206  /* error the result and return it to the client */
1208  sess->result = NULL;
1209 
1210  /* remove the bound resource */
1211  if(bres == sess->resources) {
1212  sess->resources = bres->next;
1213  } else {
1214  for(ires = sess->resources; ires != NULL; ires = ires->next)
1215  if(ires->next == bres)
1216  break;
1217  assert(ires != NULL);
1218  ires->next = bres->next;
1219  }
1220 
1221  jid_free(bres->jid);
1222  free(bres);
1223 
1224  nad_free(nad);
1225  return 0;
1226  }
1227 
1228  log_debug(ZONE, "weird, got a failed session response, with a matching id, but the action is bogus *shrug*");
1229 
1230  nad_free(nad);
1231  return 0;
1232  }
1233 
1234  /* session started */
1235  if(NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) {
1236  /* handled request */
1237  bres->sm_request[0] = '\0';
1238 
1239  /* copy the sm id */
1240  if(smid >= 0)
1241  snprintf(bres->sm_id, sizeof(bres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid));
1242 
1243  /* and remember the SM that services us */
1244  from = nad_find_attr(nad, 0, -1, "from", NULL);
1245 
1246 
1247  smcomp = malloc(NAD_AVAL_L(nad, from) + 1);
1248  snprintf(smcomp, NAD_AVAL_L(nad, from) + 1, "%.*s", NAD_AVAL_L(nad, from), NAD_AVAL(nad, from));
1249  sess->smcomp = smcomp;
1250 
1251  nad_free(nad);
1252 
1253  /* bring them online, old-skool */
1254  if(!sess->sasl_authd && sess->s) {
1255  sx_auth(sess->s, "traditional", jid_full(bres->jid));
1256  return 0;
1257  }
1258 
1259  if(sess->result) {
1260  /* return the auth result to the client */
1261  if(sess->s) sx_nad_write(sess->s, sess->result);
1262  /* or follow-up the session creation with cached presence packet */
1263  else sm_packet(sess, bres, sess->result);
1264  }
1265  sess->result = NULL;
1266 
1267  /* we're good to go */
1268  sess->active = 1;
1269 
1270  return 0;
1271  }
1272 
1273  /* handled request */
1274  bres->sm_request[0] = '\0';
1275 
1276  log_debug(ZONE, "unknown action %.*s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id));
1277 
1278  nad_free(nad);
1279 
1280  return 0;
1281  }
1282 
1283  /* client packets */
1284  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) {
1285  if(!sess->active || !sess->s) {
1286  /* its a strange world .. */
1287  log_debug(ZONE, "Got packet for %s - dropping", !sess->s ? "session without stream (PBX pipe session?)" : "inactive session");
1288  nad_free(nad);
1289  return 0;
1290  }
1291 
1292  /* sm is bouncing something */
1293  if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) {
1294  if(s) {
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 
1300  nad_free(nad);
1301  return 0;
1302  }
1303 
1304  /* we're counting packets */
1305  sess->packet_count++;
1306  sess->c2s->packet_count++;
1307 
1308  /* remove sm specifics */
1309  nad_set_attr(nad, 1, ns, "c2s", NULL, 0);
1310  nad_set_attr(nad, 1, ns, "sm", NULL, 0);
1311 
1312  /* forget about the internal namespace too */
1313  if(nad->elems[1].ns == ns)
1314  nad->elems[1].ns = nad->nss[ns].next;
1315 
1316  else {
1317  for(scan = nad->elems[1].ns; nad->nss[scan].next != -1 && nad->nss[scan].next != ns; scan = nad->nss[scan].next);
1318 
1319  /* got it */
1320  if(nad->nss[scan].next != -1)
1321  nad->nss[scan].next = nad->nss[ns].next;
1322  }
1323 
1324  sx_nad_write_elem(sess->s, nad, 1);
1325 
1326  return 0;
1327  }
1328 
1329  /* its something else */
1330  log_debug(ZONE, "unknown packet, dropping");
1331 
1332  nad_free(nad);
1333  return 0;
1334 
1335  case event_CLOSED:
1336  mio_close(c2s->mio, c2s->fd);
1337  c2s->fd = NULL;
1338  return -1;
1339  }
1340 
1341  return 0;
1342 }
1343 
1344 int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
1345  c2s_t c2s = (c2s_t) arg;
1346  int nbytes;
1347 
1348  switch(a) {
1349  case action_READ:
1350  log_debug(ZONE, "read action on fd %d", fd->fd);
1351 
1352  ioctl(fd->fd, FIONREAD, &nbytes);
1353  if(nbytes == 0) {
1354  sx_kill(c2s->router);
1355  return 0;
1356  }
1357 
1358  return sx_can_read(c2s->router);
1359 
1360  case action_WRITE:
1361  log_debug(ZONE, "write action on fd %d", fd->fd);
1362  return sx_can_write(c2s->router);
1363 
1364  case action_CLOSE:
1365  log_debug(ZONE, "close action on fd %d", fd->fd);
1366  log_write(c2s->log, LOG_NOTICE, "connection to router closed");
1367 
1368  c2s_lost_router = 1;
1369 
1370  /* we're offline */
1371  c2s->online = 0;
1372 
1373  break;
1374 
1375  case action_ACCEPT:
1376  break;
1377  }
1378 
1379  return 0;
1380 }
const char * ip
Definition: sx.h:261
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:701
struct stream_redirect_st * stream_redirect_t
_sx_state_t state
Definition: sx.h:315
#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:275
#define sx_nad_write(s, nad)
Definition: sx.h:166
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:435
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:339
int started
this is true if we've connected to the router at least once
Definition: c2s.h:305
const char * req_to
Definition: sx.h:281
unsigned int packet_count
Definition: c2s.h:98
const char * jid_full(jid_t jid)
expand and return the full
Definition: jid.c:347
jid_t jid_new(const char *id, int len)
make a new jid
Definition: jid.c:81
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
int nad_find_elem(nad_t nad, 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:204
static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
Definition: c2s.c:25
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:709
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:312
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)
Definition: sx.c:23
#define MIO_STRERROR(e)
Definition: mio.h:170
int tag
Definition: sx.h:257
int sx_can_write(sx_t s)
Definition: io.c:333
#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:734
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:667
void nad_free(nad_t nad)
free that nad
Definition: nad.c:178
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:492
const char * auth_method
Definition: sx.h:329
sx_t router
router'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
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
void nad_set_attr(nad_t nad, 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:375
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:679
#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:361
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:252
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:409
void ** val
Definition: c2s.h:401
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:403
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:679
void sx_close(sx_t s)
Definition: io.c:498
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:330
#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
int rbytes_total
Definition: sx.h:309
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:908
int retry_lost
Definition: c2s.h:209
sig_atomic_t c2s_lost_router
Definition: main.c:26
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:339
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:410
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
int nad_find_namespace(nad_t nad, int elem, const char *uri, const char *prefix)
get a matching ns on this elem, both uri and optional prefix
Definition: nad.c:262
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:203
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:513
Definition: util.h:258
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:265
#define ZONE
Definition: mio_impl.h:76
session packet handling
Definition: c2s.h:399
#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
int nad_find_attr(nad_t nad, 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:235
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'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
void nad_print(nad_t nad, int elem, const char **xml, int *len)
create a string representation of the given element (and children), point references to it ...
Definition: nad.c:1164
int sx_ssl_client_starttls(sx_plugin_t p, sx_t s, const char *pemfile, const char *private_key_password)
Definition: ssl.c:1116
char * node
Definition: jid.h:44
void(* free)(authreg_t ar)
called prior to authreg shutdown
Definition: c2s.h:364
int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
Definition: c2s.c:1344
#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:358
static void _c2s_component_presence(c2s_t c2s, nad_t nad)
Definition: c2s.c:627
int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix)
find a namespace in scope
Definition: nad.c:290
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