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