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