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