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