jabberd2
2.2.16
|
00001 /* vim: set et ts=4 sw=4: */ 00002 /* 00003 * jabberd - Jabber Open Source Server 00004 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00005 * Ryan Eatmon, Robert Norris 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00020 */ 00021 00022 #include "c2s.h" 00023 #include <stringprep.h> 00024 00025 static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { 00026 sess_t sess = (sess_t) arg; 00027 sx_buf_t buf = (sx_buf_t) data; 00028 int rlen, len, ns, elem, attr; 00029 sx_error_t *sxe; 00030 nad_t nad; 00031 char root[9]; 00032 bres_t bres, ires; 00033 stream_redirect_t redirect; 00034 00035 switch(e) { 00036 case event_WANT_READ: 00037 log_debug(ZONE, "want read"); 00038 mio_read(sess->c2s->mio, sess->fd); 00039 break; 00040 00041 case event_WANT_WRITE: 00042 log_debug(ZONE, "want write"); 00043 mio_write(sess->c2s->mio, sess->fd); 00044 break; 00045 00046 case event_READ: 00047 log_debug(ZONE, "reading from %d", sess->fd->fd); 00048 00049 /* check rate limits */ 00050 if(sess->rate != NULL) { 00051 if(rate_check(sess->rate) == 0) { 00052 00053 /* inform the app if we haven't already */ 00054 if(!sess->rate_log) { 00055 if(s->state >= state_STREAM && sess->resources != NULL) 00056 log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] is being byte rate limited", sess->fd->fd, jid_user(sess->resources->jid)); 00057 else 00058 log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] is being byte rate limited", sess->fd->fd, sess->ip, sess->port); 00059 00060 sess->rate_log = 1; 00061 } 00062 00063 return -1; 00064 } 00065 00066 /* find out how much we can have */ 00067 rlen = rate_left(sess->rate); 00068 if(rlen > buf->len) 00069 rlen = buf->len; 00070 } 00071 00072 /* no limit, just read as much as we can */ 00073 else 00074 rlen = buf->len; 00075 00076 /* do the read */ 00077 len = recv(sess->fd->fd, buf->data, rlen, 0); 00078 00079 /* update rate limits */ 00080 if(sess->rate != NULL) 00081 rate_add(sess->rate, len); 00082 00083 if(len < 0) { 00084 if(MIO_WOULDBLOCK) { 00085 buf->len = 0; 00086 return 0; 00087 } 00088 00089 if(s->state >= state_STREAM && sess->resources != NULL) 00090 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); 00091 else 00092 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); 00093 00094 sx_kill(s); 00095 00096 return -1; 00097 } 00098 00099 else if(len == 0) { 00100 /* they went away */ 00101 sx_kill(s); 00102 00103 return -1; 00104 } 00105 00106 log_debug(ZONE, "read %d bytes", len); 00107 00108 /* If the first chars are "GET " then it's for HTTP (GET ....) 00109 and if we configured http client forwarding to a real http server */ 00110 if (sess->c2s->http_forward && !sess->active && !sess->sasl_authd 00111 && sess->result == NULL && len >= 4 && strncmp("GET ", buf->data, 4) == 0) { 00112 char* http = 00113 "HTTP/1.0 301 Found\r\n" 00114 "Location: %s\r\n" 00115 "Server: " PACKAGE_STRING "\r\n" 00116 "Expires: Fri, 10 Oct 1997 10:10:10 GMT\r\n" 00117 "Pragma: no-cache\r\n" 00118 "Cache-control: private\r\n" 00119 "Connection: close\r\n\r\n"; 00120 char *answer; 00121 00122 len = strlen(sess->c2s->http_forward) + strlen(http); 00123 answer = malloc(len * sizeof(char)); 00124 sprintf (answer, http, sess->c2s->http_forward); 00125 00126 log_write(sess->c2s->log, LOG_NOTICE, "[%d] bouncing HTTP request to %s", sess->fd->fd, sess->c2s->http_forward); 00127 00128 /* send HTTP answer */ 00129 len = send(sess->fd->fd, answer, len-1, 0); 00130 00131 free(answer); 00132 00133 /* close connection */ 00134 sx_kill(s); 00135 00136 return -1; 00137 } 00138 00139 buf->len = len; 00140 00141 return len; 00142 00143 case event_WRITE: 00144 log_debug(ZONE, "writing to %d", sess->fd->fd); 00145 00146 len = send(sess->fd->fd, buf->data, buf->len, 0); 00147 if(len >= 0) { 00148 log_debug(ZONE, "%d bytes written", len); 00149 return len; 00150 } 00151 00152 if(MIO_WOULDBLOCK) 00153 return 0; 00154 00155 if(s->state >= state_OPEN && sess->resources != NULL) 00156 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); 00157 else 00158 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); 00159 00160 sx_kill(s); 00161 00162 return -1; 00163 00164 case event_ERROR: 00165 sxe = (sx_error_t *) data; 00166 if(sess->resources != NULL) 00167 log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] error: %s (%s)", sess->fd->fd, jid_user(sess->resources->jid), sxe->generic, sxe->specific); 00168 else 00169 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); 00170 00171 break; 00172 00173 case event_STREAM: 00174 00175 if(s->req_to == NULL) { 00176 log_debug(ZONE, "no stream to provided, closing"); 00177 sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header"); 00178 sx_close(s); 00179 00180 return 0; 00181 } 00182 00183 /* send a see-other-host error if we're configured to do so */ 00184 redirect = (stream_redirect_t) xhash_get(sess->c2s->stream_redirects, s->req_to); 00185 if (redirect != NULL) { 00186 log_debug(ZONE, "redirecting client's stream using see-other-host for domain: '%s'", s->req_to); 00187 len = strlen(redirect->to_address) + strlen(redirect->to_port) + 1; 00188 char *other_host = (char *) malloc(len+1); 00189 snprintf(other_host, len+1, "%s:%s", redirect->to_address, redirect->to_port); 00190 sx_error_extended(s, stream_err_SEE_OTHER_HOST, other_host); 00191 free(other_host); 00192 sx_close(s); 00193 00194 return 0; 00195 } 00196 00197 /* setup the host */ 00198 sess->host = xhash_get(sess->c2s->hosts, s->req_to); 00199 00200 if(sess->host == NULL && sess->c2s->vhost == NULL) { 00201 log_debug(ZONE, "no host available for requested domain '%s'", s->req_to); 00202 sx_error(s, stream_err_HOST_UNKNOWN, "service requested for unknown domain"); 00203 sx_close(s); 00204 00205 return 0; 00206 } 00207 00208 if(xhash_get(sess->c2s->sm_avail, s->req_to) == NULL) { 00209 log_debug(ZONE, "sm for domain '%s' is not online", s->req_to); 00210 sx_error(s, stream_err_HOST_GONE, "session manager for requested domain is not available"); 00211 sx_close(s); 00212 00213 return 0; 00214 } 00215 00216 if(sess->host == NULL) { 00217 /* create host on-fly */ 00218 sess->host = (host_t) pmalloc(xhash_pool(sess->c2s->hosts), sizeof(struct host_st)); 00219 memcpy(sess->host, sess->c2s->vhost, sizeof(struct host_st)); 00220 sess->host->realm = pstrdup(xhash_pool(sess->c2s->hosts), s->req_to); 00221 xhash_put(sess->c2s->hosts, pstrdup(xhash_pool(sess->c2s->hosts), s->req_to), sess->host); 00222 } 00223 00224 #ifdef HAVE_SSL 00225 if(sess->host->host_pemfile != NULL) 00226 sess->s->flags |= SX_SSL_STARTTLS_OFFER; 00227 if(sess->host->host_require_starttls) 00228 sess->s->flags |= SX_SSL_STARTTLS_REQUIRE; 00229 #endif 00230 break; 00231 00232 case event_PACKET: 00233 /* we're counting packets */ 00234 sess->packet_count++; 00235 sess->c2s->packet_count++; 00236 00237 /* check rate limits */ 00238 if(sess->stanza_rate != NULL) { 00239 if(rate_check(sess->stanza_rate) == 0) { 00240 00241 /* inform the app if we haven't already */ 00242 if(!sess->stanza_rate_log) { 00243 if(s->state >= state_STREAM && sess->resources != NULL) 00244 log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s] is being stanza rate limited", sess->fd->fd, jid_user(sess->resources->jid)); 00245 else 00246 log_write(sess->c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] is being stanza rate limited", sess->fd->fd, sess->ip, sess->port); 00247 00248 sess->stanza_rate_log = 1; 00249 } 00250 } 00251 00252 /* update rate limits */ 00253 rate_add(sess->stanza_rate, 1); 00254 } 00255 00256 nad = (nad_t) data; 00257 00258 /* we only want (message|presence|iq) in jabber:client, everything else gets dropped */ 00259 snprintf(root, 9, "%.*s", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0)); 00260 if(NAD_ENS(nad, 0) != nad_find_namespace(nad, 0, uri_CLIENT, NULL) || 00261 (strcmp(root, "message") != 0 && strcmp(root, "presence") != 0 && strcmp(root, "iq") != 0)) { 00262 nad_free(nad); 00263 return 0; 00264 } 00265 00266 /* resource bind */ 00267 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) { 00268 bres_t bres; 00269 jid_t jid = jid_new(sess->s->auth_id, -1); 00270 00271 /* get the resource */ 00272 elem = nad_find_elem(nad, elem, ns, "resource", 1); 00273 00274 /* user-specified resource */ 00275 if(elem >= 0) { 00276 char resource_buf[1024]; 00277 00278 if(NAD_CDATA_L(nad, elem) == 0) { 00279 log_debug(ZONE, "empty resource specified on bind"); 00280 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST)); 00281 00282 return 0; 00283 } 00284 00285 snprintf(resource_buf, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem)); 00286 /* Put resource into JID */ 00287 if (jid == NULL || jid_reset_components(jid, jid->node, jid->domain, resource_buf) == NULL) { 00288 log_debug(ZONE, "invalid jid data"); 00289 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST)); 00290 00291 return 0; 00292 } 00293 00294 /* check if resource already bound */ 00295 for(bres = sess->resources; bres != NULL; bres = bres->next) 00296 if(strcmp(bres->jid->resource, jid->resource) == 0){ 00297 log_debug(ZONE, "resource /%s already bound - generating", jid->resource); 00298 jid_random_part(jid, jid_RESOURCE); 00299 } 00300 } 00301 else { 00302 /* generate random resource */ 00303 log_debug(ZONE, "no resource given - generating"); 00304 jid_random_part(jid, jid_RESOURCE); 00305 } 00306 00307 /* attach new bound jid holder */ 00308 bres = (bres_t) calloc(1, sizeof(struct bres_st)); 00309 bres->jid = jid; 00310 if(sess->resources != NULL) { 00311 for(ires = sess->resources; ires->next != NULL; ires = ires->next); 00312 ires->next = bres; 00313 } else 00314 sess->resources = bres; 00315 00316 sess->bound += 1; 00317 00318 log_write(sess->c2s->log, LOG_NOTICE, "[%d] bound: jid=%s", sess->s->tag, jid_full(bres->jid)); 00319 00320 /* build a result packet, we'll send this back to the client after we have a session for them */ 00321 sess->result = nad_new(); 00322 00323 ns = nad_add_namespace(sess->result, uri_CLIENT, NULL); 00324 00325 nad_append_elem(sess->result, ns, "iq", 0); 00326 nad_set_attr(sess->result, 0, -1, "type", "result", 6); 00327 00328 attr = nad_find_attr(nad, 0, -1, "id", NULL); 00329 if(attr >= 0) 00330 nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00331 00332 ns = nad_add_namespace(sess->result, uri_BIND, NULL); 00333 00334 nad_append_elem(sess->result, ns, "bind", 1); 00335 nad_append_elem(sess->result, ns, "jid", 2); 00336 nad_append_cdata(sess->result, jid_full(bres->jid), strlen(jid_full(bres->jid)), 3); 00337 00338 /* our local id */ 00339 sprintf(bres->c2s_id, "%d", sess->s->tag); 00340 00341 /* start a session with the sm */ 00342 sm_start(sess, bres); 00343 00344 /* finished with the nad */ 00345 nad_free(nad); 00346 00347 /* handled */ 00348 return 0; 00349 } 00350 00351 /* resource unbind */ 00352 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) { 00353 char resource_buf[1024]; 00354 bres_t bres; 00355 00356 /* get the resource */ 00357 elem = nad_find_elem(nad, elem, ns, "resource", 1); 00358 00359 if(elem < 0 || NAD_CDATA_L(nad, elem) == 0) { 00360 log_debug(ZONE, "no/empty resource given to unbind"); 00361 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST)); 00362 00363 return 0; 00364 } 00365 00366 snprintf(resource_buf, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem)); 00367 if(stringprep_xmpp_resourceprep(resource_buf, 1024) != 0) { 00368 log_debug(ZONE, "cannot resourceprep"); 00369 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_BAD_REQUEST)); 00370 00371 return 0; 00372 } 00373 00374 /* check if resource bound */ 00375 for(bres = sess->resources; bres != NULL; bres = bres->next) 00376 if(strcmp(bres->jid->resource, resource_buf) == 0) 00377 break; 00378 00379 if(bres == NULL) { 00380 log_debug(ZONE, "resource /%s not bound", resource_buf); 00381 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_ITEM_NOT_FOUND)); 00382 00383 return 0; 00384 } 00385 00386 /* build a result packet, we'll send this back to the client after we close a session for them */ 00387 sess->result = nad_new(); 00388 00389 ns = nad_add_namespace(sess->result, uri_CLIENT, NULL); 00390 00391 nad_append_elem(sess->result, ns, "iq", 0); 00392 nad_set_attr(sess->result, 0, -1, "type", "result", 6); 00393 00394 attr = nad_find_attr(nad, 0, -1, "id", NULL); 00395 if(attr >= 0) 00396 nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00397 00398 /* end a session with the sm */ 00399 sm_end(sess, bres); 00400 00401 /* finished with the nad */ 00402 nad_free(nad); 00403 00404 /* handled */ 00405 return 0; 00406 } 00407 00408 /* pre-session requests */ 00409 if(!sess->active && sess->sasl_authd && sess->result == NULL && strcmp(root, "iq") == 0 && nad_find_attr(nad, 0, -1, "type", "set") >= 0) { 00410 log_debug(ZONE, "unrecognised pre-session packet, bye"); 00411 log_write(sess->c2s->log, LOG_NOTICE, "[%d] unrecognized pre-session packet, closing stream", sess->s->tag); 00412 00413 sx_error(s, stream_err_NOT_AUTHORIZED, "unrecognized pre-session stanza"); 00414 sx_close(s); 00415 00416 nad_free(nad); 00417 return 0; 00418 } 00419 00420 #ifdef HAVE_SSL 00421 /* drop packets if they have to starttls and they haven't */ 00422 if((sess->s->flags & SX_SSL_STARTTLS_REQUIRE) && sess->s->ssf == 0) { 00423 log_debug(ZONE, "pre STARTTLS packet, dropping"); 00424 log_write(sess->c2s->log, LOG_NOTICE, "[%d] got pre STARTTLS packet, dropping", sess->s->tag); 00425 00426 sx_error(s, stream_err_POLICY_VIOLATION, "STARTTLS is required for this stream"); 00427 00428 nad_free(nad); 00429 return 0; 00430 } 00431 #endif 00432 00433 /* handle iq:auth packets */ 00434 if(authreg_process(sess->c2s, sess, nad) == 0) 00435 return 0; 00436 00437 /* drop it if no session */ 00438 if(!sess->active) { 00439 log_debug(ZONE, "pre-session packet, bye"); 00440 log_write(sess->c2s->log, LOG_NOTICE, "[%d] packet sent before session start, closing stream", sess->s->tag); 00441 00442 sx_error(s, stream_err_NOT_AUTHORIZED, "stanza sent before session start"); 00443 sx_close(s); 00444 00445 nad_free(nad); 00446 return 0; 00447 } 00448 00449 /* validate 'from' */ 00450 assert(sess->resources != NULL); 00451 if(sess->bound > 1) { 00452 bres = NULL; 00453 if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0) 00454 for(bres = sess->resources; bres != NULL; bres = bres->next) 00455 if(strncmp(jid_full(bres->jid), NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)) == 0) 00456 break; 00457 00458 if(bres == NULL) { 00459 if(attr >= 0) { 00460 log_debug(ZONE, "packet from: %.*s that has not bound the resource", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr)); 00461 } else { 00462 log_debug(ZONE, "packet without 'from' on multiple resource stream"); 00463 } 00464 00465 sx_nad_write(sess->s, stanza_error(nad, 0, stanza_err_UNKNOWN_SENDER)); 00466 00467 return 0; 00468 } 00469 } else 00470 bres = sess->resources; 00471 00472 /* pass it on to the session manager */ 00473 sm_packet(sess, bres, nad); 00474 00475 break; 00476 00477 case event_OPEN: 00478 00479 /* only send a result and bring us online if this wasn't a sasl auth */ 00480 if(strlen(s->auth_method) < 4 || strncmp("SASL", s->auth_method, 4) != 0) { 00481 /* return the auth result to the client */ 00482 sx_nad_write(s, sess->result); 00483 sess->result = NULL; 00484 00485 /* we're good to go */ 00486 sess->active = 1; 00487 } 00488 00489 /* they sasl auth'd, so we only want the new-style session start */ 00490 else { 00491 log_write(sess->c2s->log, LOG_NOTICE, "[%d] %s authentication succeeded: %s %s:%d%s%s", 00492 sess->s->tag, &sess->s->auth_method[5], 00493 sess->s->auth_id, sess->s->ip, sess->s->port, 00494 sess->s->ssf ? " TLS" : "", sess->s->compressed ? " ZLIB" : "" 00495 ); 00496 sess->sasl_authd = 1; 00497 } 00498 00499 break; 00500 00501 case event_CLOSED: 00502 mio_close(sess->c2s->mio, sess->fd); 00503 sess->fd = NULL; 00504 return -1; 00505 } 00506 00507 return 0; 00508 } 00509 00510 static int _c2s_client_accept_check(c2s_t c2s, mio_fd_t fd, char *ip) { 00511 rate_t rt; 00512 00513 if(access_check(c2s->access, ip) == 0) { 00514 log_write(c2s->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd->fd, ip); 00515 return 1; 00516 } 00517 00518 if(c2s->conn_rate_total != 0) { 00519 rt = (rate_t) xhash_get(c2s->conn_rates, ip); 00520 if(rt == NULL) { 00521 rt = rate_new(c2s->conn_rate_total, c2s->conn_rate_seconds, c2s->conn_rate_wait); 00522 xhash_put(c2s->conn_rates, pstrdup(xhash_pool(c2s->conn_rates), ip), (void *) rt); 00523 pool_cleanup(xhash_pool(c2s->conn_rates), (void (*)(void *)) rate_free, rt); 00524 } 00525 00526 if(rate_check(rt) == 0) { 00527 log_write(c2s->log, LOG_NOTICE, "[%d] [%s] is being connect rate limited", fd->fd, ip); 00528 return 1; 00529 } 00530 00531 rate_add(rt, 1); 00532 } 00533 00534 return 0; 00535 } 00536 00537 static int _c2s_client_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { 00538 sess_t sess = (sess_t) arg; 00539 c2s_t c2s = (c2s_t) arg; 00540 bres_t bres; 00541 struct sockaddr_storage sa; 00542 int namelen = sizeof(sa), port, nbytes, flags = 0; 00543 00544 switch(a) { 00545 case action_READ: 00546 log_debug(ZONE, "read action on fd %d", fd->fd); 00547 00548 /* they did something */ 00549 sess->last_activity = time(NULL); 00550 00551 ioctl(fd->fd, FIONREAD, &nbytes); 00552 if(nbytes == 0) { 00553 sx_kill(sess->s); 00554 return 0; 00555 } 00556 00557 return sx_can_read(sess->s); 00558 00559 case action_WRITE: 00560 log_debug(ZONE, "write action on fd %d", fd->fd); 00561 00562 return sx_can_write(sess->s); 00563 00564 case action_CLOSE: 00565 log_debug(ZONE, "close action on fd %d", fd->fd); 00566 00567 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); 00568 00569 /* tell the sm to close their session */ 00570 if(sess->active) 00571 for(bres = sess->resources; bres != NULL; bres = bres->next) 00572 sm_end(sess, bres); 00573 00574 jqueue_push(sess->c2s->dead, (void *) sess->s, 0); 00575 00576 xhash_zap(sess->c2s->sessions, sess->skey); 00577 00578 jqueue_push(sess->c2s->dead_sess, (void *) sess, 0); 00579 00580 break; 00581 00582 case action_ACCEPT: 00583 log_debug(ZONE, "accept action on fd %d", fd->fd); 00584 00585 getpeername(fd->fd, (struct sockaddr *) &sa, &namelen); 00586 port = j_inet_getport(&sa); 00587 00588 log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] connect", fd->fd, (char *) data, port); 00589 00590 if(_c2s_client_accept_check(c2s, fd, (char *) data) != 0) 00591 return 1; 00592 00593 sess = (sess_t) calloc(1, sizeof(struct sess_st)); 00594 00595 sess->c2s = c2s; 00596 00597 sess->fd = fd; 00598 00599 sess->ip = strdup((char *) data); 00600 sess->port = port; 00601 00602 /* they did something */ 00603 sess->last_activity = time(NULL); 00604 00605 sess->s = sx_new(c2s->sx_env, fd->fd, _c2s_client_sx_callback, (void *) sess); 00606 mio_app(m, fd, _c2s_client_mio_callback, (void *) sess); 00607 00608 if(c2s->stanza_size_limit != 0) 00609 sess->s->rbytesmax = c2s->stanza_size_limit; 00610 00611 if(c2s->byte_rate_total != 0) 00612 sess->rate = rate_new(c2s->byte_rate_total, c2s->byte_rate_seconds, c2s->byte_rate_wait); 00613 00614 if(c2s->stanza_rate_total != 0) 00615 sess->stanza_rate = rate_new(c2s->stanza_rate_total, c2s->stanza_rate_seconds, c2s->stanza_rate_wait); 00616 00617 /* give IP to SX */ 00618 sess->s->ip = sess->ip; 00619 sess->s->port = sess->port; 00620 00621 /* find out which port this is */ 00622 getsockname(fd->fd, (struct sockaddr *) &sa, &namelen); 00623 port = j_inet_getport(&sa); 00624 00625 /* remember it */ 00626 sprintf(sess->skey, "%d", fd->fd); 00627 xhash_put(c2s->sessions, sess->skey, (void *) sess); 00628 00629 flags = SX_SASL_OFFER; 00630 #ifdef HAVE_SSL 00631 /* go ssl wrappermode if they're on the ssl port */ 00632 if(port == c2s->local_ssl_port) 00633 flags |= SX_SSL_WRAPPER; 00634 #endif 00635 #ifdef HAVE_LIBZ 00636 if(c2s->compression) 00637 flags |= SX_COMPRESS_OFFER; 00638 #endif 00639 sx_server_init(sess->s, flags); 00640 00641 break; 00642 } 00643 00644 return 0; 00645 } 00646 00647 static void _c2s_component_presence(c2s_t c2s, nad_t nad) { 00648 int attr; 00649 char from[1024]; 00650 sess_t sess; 00651 union xhashv xhv; 00652 00653 if((attr = nad_find_attr(nad, 0, -1, "from", NULL)) < 0) { 00654 nad_free(nad); 00655 return; 00656 } 00657 00658 strncpy(from, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00659 from[NAD_AVAL_L(nad, attr)] = '\0'; 00660 00661 if(nad_find_attr(nad, 0, -1, "type", NULL) < 0) { 00662 log_debug(ZONE, "component available from '%s'", from); 00663 00664 log_debug(ZONE, "sm for serviced domain '%s' online", from); 00665 00666 xhash_put(c2s->sm_avail, pstrdup(xhash_pool(c2s->sm_avail), from), (void *) 1); 00667 00668 nad_free(nad); 00669 return; 00670 } 00671 00672 if(nad_find_attr(nad, 0, -1, "type", "unavailable") < 0) { 00673 nad_free(nad); 00674 return; 00675 } 00676 00677 log_debug(ZONE, "component unavailable from '%s'", from); 00678 00679 if(xhash_get(c2s->sm_avail, from) != NULL) { 00680 log_debug(ZONE, "sm for serviced domain '%s' offline", from); 00681 00682 if(xhash_iter_first(c2s->sessions)) 00683 do { 00684 xhv.sess_val = &sess; 00685 xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val); 00686 00687 if(sess->resources != NULL && strcmp(sess->resources->jid->domain, from) == 0) { 00688 log_debug(ZONE, "killing session %s", jid_user(sess->resources->jid)); 00689 00690 sess->active = 0; 00691 if(sess->s) sx_close(sess->s); 00692 } 00693 } while(xhash_iter_next(c2s->sessions)); 00694 00695 xhash_zap(c2s->sm_avail, from); 00696 } 00697 } 00698 00699 int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { 00700 c2s_t c2s = (c2s_t) arg; 00701 sx_buf_t buf = (sx_buf_t) data; 00702 sx_error_t *sxe; 00703 nad_t nad; 00704 int len, elem, from, c2sid, smid, action, id, ns, attr, scan, replaced; 00705 char skey[44]; 00706 sess_t sess; 00707 bres_t bres, ires; 00708 00709 switch(e) { 00710 case event_WANT_READ: 00711 log_debug(ZONE, "want read"); 00712 mio_read(c2s->mio, c2s->fd); 00713 break; 00714 00715 case event_WANT_WRITE: 00716 log_debug(ZONE, "want write"); 00717 mio_write(c2s->mio, c2s->fd); 00718 break; 00719 00720 case event_READ: 00721 log_debug(ZONE, "reading from %d", c2s->fd->fd); 00722 00723 /* do the read */ 00724 len = recv(c2s->fd->fd, buf->data, buf->len, 0); 00725 00726 if(len < 0) { 00727 if(MIO_WOULDBLOCK) { 00728 buf->len = 0; 00729 return 0; 00730 } 00731 00732 log_write(c2s->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR); 00733 00734 sx_kill(s); 00735 00736 return -1; 00737 } 00738 00739 else if(len == 0) { 00740 /* they went away */ 00741 sx_kill(s); 00742 00743 return -1; 00744 } 00745 00746 log_debug(ZONE, "read %d bytes", len); 00747 00748 buf->len = len; 00749 00750 return len; 00751 00752 case event_WRITE: 00753 log_debug(ZONE, "writing to %d", c2s->fd->fd); 00754 00755 len = send(c2s->fd->fd, buf->data, buf->len, 0); 00756 if(len >= 0) { 00757 log_debug(ZONE, "%d bytes written", len); 00758 return len; 00759 } 00760 00761 if(MIO_WOULDBLOCK) 00762 return 0; 00763 00764 log_write(c2s->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", c2s->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR); 00765 00766 sx_kill(s); 00767 00768 return -1; 00769 00770 case event_ERROR: 00771 sxe = (sx_error_t *) data; 00772 log_write(c2s->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific); 00773 00774 if(sxe->code == SX_ERR_AUTH) 00775 sx_close(s); 00776 00777 break; 00778 00779 case event_STREAM: 00780 break; 00781 00782 case event_OPEN: 00783 log_write(c2s->log, LOG_NOTICE, "connection to router established"); 00784 00785 /* set connection attempts counter */ 00786 c2s->retry_left = c2s->retry_lost; 00787 00788 nad = nad_new(); 00789 ns = nad_add_namespace(nad, uri_COMPONENT, NULL); 00790 nad_append_elem(nad, ns, "bind", 0); 00791 nad_append_attr(nad, -1, "name", c2s->id); 00792 00793 log_debug(ZONE, "requesting component bind for '%s'", c2s->id); 00794 00795 sx_nad_write(c2s->router, nad); 00796 00797 return 0; 00798 00799 case event_PACKET: 00800 nad = (nad_t) data; 00801 00802 /* drop unqualified packets */ 00803 if(NAD_ENS(nad, 0) < 0) { 00804 nad_free(nad); 00805 return 0; 00806 } 00807 00808 /* watch for the features packet */ 00809 if(s->state == state_STREAM) { 00810 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) { 00811 log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping"); 00812 nad_free(nad); 00813 return 0; 00814 } 00815 00816 #ifdef HAVE_SSL 00817 /* starttls if we can */ 00818 if(c2s->sx_ssl != NULL && c2s->router_pemfile != NULL && s->ssf == 0) { 00819 ns = nad_find_scoped_namespace(nad, uri_TLS, NULL); 00820 if(ns >= 0) { 00821 elem = nad_find_elem(nad, 0, ns, "starttls", 1); 00822 if(elem >= 0) { 00823 if(sx_ssl_client_starttls(c2s->sx_ssl, s, c2s->router_pemfile) == 0) { 00824 nad_free(nad); 00825 return 0; 00826 } 00827 log_write(c2s->log, LOG_ERR, "unable to establish encrypted session with router"); 00828 } 00829 } 00830 } 00831 #endif 00832 00833 /* !!! pull the list of mechanisms, and choose the best one. 00834 * if there isn't an appropriate one, error and bail */ 00835 00836 /* authenticate */ 00837 sx_sasl_auth(c2s->sx_sasl, s, "jabberd-router", "DIGEST-MD5", c2s->router_user, c2s->router_pass); 00838 00839 nad_free(nad); 00840 return 0; 00841 } 00842 00843 /* watch for the bind response */ 00844 if(s->state == state_OPEN && !c2s->online) { 00845 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) { 00846 log_debug(ZONE, "got a packet from router, but we're not online, dropping"); 00847 nad_free(nad); 00848 return 0; 00849 } 00850 00851 /* catch errors */ 00852 attr = nad_find_attr(nad, 0, -1, "error", NULL); 00853 if(attr >= 0) { 00854 log_write(c2s->log, LOG_ERR, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr)); 00855 exit(1); 00856 } 00857 00858 log_debug(ZONE, "coming online"); 00859 00860 /* if we're coming online for the first time, setup listening sockets */ 00861 #ifdef HAVE_SSL 00862 if(c2s->server_fd == 0 && c2s->server_ssl_fd == 0) { 00863 #else 00864 if(c2s->server_fd == 0) { 00865 #endif 00866 if(c2s->local_port != 0) { 00867 c2s->server_fd = mio_listen(c2s->mio, c2s->local_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s); 00868 if(c2s->server_fd == NULL) 00869 log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_port); 00870 else 00871 log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for connections", c2s->local_ip, c2s->local_port); 00872 } else 00873 c2s->server_fd = NULL; 00874 00875 #ifdef HAVE_SSL 00876 if(c2s->local_ssl_port != 0 && c2s->local_pemfile != NULL) { 00877 c2s->server_ssl_fd = mio_listen(c2s->mio, c2s->local_ssl_port, c2s->local_ip, _c2s_client_mio_callback, (void *) c2s); 00878 if(c2s->server_ssl_fd == NULL) 00879 log_write(c2s->log, LOG_ERR, "[%s, port=%d] failed to listen", c2s->local_ip, c2s->local_ssl_port); 00880 else 00881 log_write(c2s->log, LOG_NOTICE, "[%s, port=%d] listening for SSL connections", c2s->local_ip, c2s->local_ssl_port); 00882 } else 00883 c2s->server_ssl_fd = NULL; 00884 #endif 00885 } 00886 00887 #ifdef HAVE_SSL 00888 if(c2s->server_fd == NULL && c2s->server_ssl_fd == NULL && c2s->pbx_pipe == NULL) { 00889 log_write(c2s->log, LOG_ERR, "both normal and SSL ports are disabled, nothing to do!"); 00890 #else 00891 if(c2s->server_fd == NULL && c2s->pbx_pipe == NULL) { 00892 log_write(c2s->log, LOG_ERR, "server port is disabled, nothing to do!"); 00893 #endif 00894 exit(1); 00895 } 00896 00897 /* open PBX integration FIFO */ 00898 if(c2s->pbx_pipe != NULL) 00899 c2s_pbx_init(c2s); 00900 00901 /* we're online */ 00902 c2s->online = c2s->started = 1; 00903 log_write(c2s->log, LOG_NOTICE, "ready for connections", c2s->id); 00904 00905 nad_free(nad); 00906 return 0; 00907 } 00908 00909 /* need component packets */ 00910 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) { 00911 log_debug(ZONE, "wanted component packet, dropping"); 00912 nad_free(nad); 00913 return 0; 00914 } 00915 00916 /* component presence */ 00917 if(NAD_ENAME_L(nad, 0) == 8 && strncmp("presence", NAD_ENAME(nad, 0), 8) == 0) { 00918 _c2s_component_presence(c2s, nad); 00919 return 0; 00920 } 00921 00922 /* we want route */ 00923 if(NAD_ENAME_L(nad, 0) != 5 || strncmp("route", NAD_ENAME(nad, 0), 5) != 0) { 00924 log_debug(ZONE, "wanted {component}route, dropping"); 00925 nad_free(nad); 00926 return 0; 00927 } 00928 00929 /* only handle unicasts */ 00930 if(nad_find_attr(nad, 0, -1, "type", NULL) >= 0) { 00931 log_debug(ZONE, "non-unicast packet, dropping"); 00932 nad_free(nad); 00933 return 0; 00934 } 00935 00936 /* need some payload */ 00937 if(nad->ecur == 1) { 00938 log_debug(ZONE, "no route payload, dropping"); 00939 nad_free(nad); 00940 return 0; 00941 } 00942 00943 ns = nad_find_namespace(nad, 1, uri_SESSION, NULL); 00944 if(ns < 0) { 00945 log_debug(ZONE, "not a c2s packet, dropping"); 00946 nad_free(nad); 00947 return 0; 00948 } 00949 00950 /* figure out the session */ 00951 c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL); 00952 if(c2sid < 0) { 00953 log_debug(ZONE, "no c2s id on payload, dropping"); 00954 nad_free(nad); 00955 return 0; 00956 } 00957 snprintf(skey, sizeof(skey), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid)); 00958 00959 /* find the session, quietly drop if we don't have it */ 00960 sess = xhash_get(c2s->sessions, skey); 00961 if(sess == NULL) { 00962 /* if we get this, the SM probably thinks the session is still active 00963 * so we need to tell SM to free it up */ 00964 log_debug(ZONE, "no session for %s", skey); 00965 00966 /* check if it's a started action; otherwise we could end up in an infinite loop 00967 * trying to tell SM to close in response to errors */ 00968 action = nad_find_attr(nad, 1, -1, "action", NULL); 00969 if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) { 00970 int target; 00971 bres_t tres; 00972 sess_t tsess; 00973 00974 log_write(c2s->log, LOG_NOTICE, "session %s does not exist; telling sm to close", skey); 00975 00976 /* we don't have a session and we don't have a resource; we need to forge them both 00977 * to get SM to close stuff */ 00978 target = nad_find_attr(nad, 1, -1, "target", NULL); 00979 smid = nad_find_attr(nad, 1, ns, "sm", NULL); 00980 if(target < 0 || smid < 0) { 00981 char *buf; 00982 int len; 00983 nad_print(nad, 0, &buf, &len); 00984 log_write(c2s->log, LOG_NOTICE, "sm sent an invalid start packet: %.*s", len, buf ); 00985 nad_free(nad); 00986 return 0; 00987 } 00988 00989 /* build temporary resource to close session for */ 00990 tres = NULL; 00991 tres = (bres_t) calloc(1, sizeof(struct bres_st)); 00992 tres->jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target)); 00993 00994 strncpy(tres->c2s_id, skey, sizeof(tres->c2s_id)); 00995 snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid)); 00996 00997 /* make a temporary session */ 00998 tsess = (sess_t) calloc(1, sizeof(struct sess_st)); 00999 tsess->c2s = c2s; 01000 tsess->result = nad_new(); 01001 strncpy(tsess->skey, skey, sizeof(tsess->skey)); 01002 01003 /* end a session with the sm */ 01004 sm_end(tsess, tres); 01005 01006 /* free our temporary messes */ 01007 nad_free(tsess->result); 01008 jid_free(tres->jid); //TODO will this crash? 01009 free(tsess); 01010 free(tres); 01011 } 01012 01013 nad_free(nad); 01014 return 0; 01015 } 01016 01017 /* if they're pre-stream, then this is leftovers from a previous session */ 01018 if(sess->s && sess->s->state < state_STREAM) { 01019 log_debug(ZONE, "session %s is pre-stream", skey); 01020 01021 nad_free(nad); 01022 return 0; 01023 } 01024 01025 /* check the sm session id if they gave us one */ 01026 smid = nad_find_attr(nad, 1, ns, "sm", NULL); 01027 01028 /* get the action attribute */ 01029 action = nad_find_attr(nad, 1, -1, "action", NULL); 01030 01031 /* first user created packets - these are out of session */ 01032 if(action >= 0 && NAD_AVAL_L(nad, action) == 7 && strncmp("created", NAD_AVAL(nad, action), 7) == 0) { 01033 01034 nad_free(nad); 01035 01036 /* return the result to the client */ 01037 sx_nad_write(sess->s, sess->result); 01038 sess->result = NULL; 01039 01040 return 0; 01041 } 01042 01043 /* route errors */ 01044 if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) { 01045 log_debug(ZONE, "routing error"); 01046 01047 if(sess->s) { 01048 sx_error(sess->s, stream_err_INTERNAL_SERVER_ERROR, "internal server error"); 01049 sx_close(sess->s); 01050 } 01051 01052 nad_free(nad); 01053 return 0; 01054 } 01055 01056 /* all other packets need to contain an sm ID */ 01057 if (smid < 0) { 01058 log_debug(ZONE, "received packet from sm without an sm ID, dropping"); 01059 nad_free(nad); 01060 return 0; 01061 } 01062 01063 /* find resource that we got packet for */ 01064 bres = NULL; 01065 if(smid >= 0) 01066 for(bres = sess->resources; bres != NULL; bres = bres->next){ 01067 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)) 01068 break; 01069 } 01070 if(bres == NULL) { 01071 jid_t jid = NULL; 01072 bres_t tres = NULL; 01073 01074 /* if it's a failure, just drop it */ 01075 if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) { 01076 nad_free(nad); 01077 return 0; 01078 } 01079 01080 /* build temporary resource to close session for */ 01081 tres = (bres_t) calloc(1, sizeof(struct bres_st)); 01082 if(sess->s) { 01083 jid = jid_new(sess->s->auth_id, -1); 01084 sprintf(tres->c2s_id, "%d", sess->s->tag); 01085 } 01086 else { 01087 /* does not have SX - extract values from route packet */ 01088 int c2sid, target; 01089 c2sid = nad_find_attr(nad, 1, ns, "c2s", NULL); 01090 target = nad_find_attr(nad, 1, -1, "target", NULL); 01091 if(c2sid < 0 || target < 0) { 01092 log_debug(ZONE, "needed ids not found - c2sid:%d target:%d", c2sid, target); 01093 nad_free(nad); 01094 free(tres); 01095 return 0; 01096 } 01097 jid = jid_new(NAD_AVAL(nad, target), NAD_AVAL_L(nad, target)); 01098 snprintf(tres->c2s_id, sizeof(tres->c2s_id), "%.*s", NAD_AVAL_L(nad, c2sid), NAD_AVAL(nad, c2sid)); 01099 } 01100 tres->jid = jid; 01101 snprintf(tres->sm_id, sizeof(tres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid)); 01102 01103 if(sess->resources) { 01104 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)); 01105 } else { 01106 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)); 01107 } 01108 01109 /* end a session with the sm */ 01110 sm_end(sess, tres); 01111 01112 /* finished with the nad */ 01113 nad_free(nad); 01114 01115 /* free temp objects */ 01116 jid_free(jid); 01117 free(tres); 01118 01119 return 0; 01120 } 01121 01122 /* session control packets */ 01123 if(NAD_ENS(nad, 1) == ns && action >= 0) { 01124 /* end responses */ 01125 01126 /* !!! this "replaced" stuff is a hack - its really a subaction of "ended". 01127 * hurrah, another control protocol rewrite is needed :( 01128 */ 01129 01130 replaced = 0; 01131 if(NAD_AVAL_L(nad, action) == 8 && strncmp("replaced", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0) 01132 replaced = 1; 01133 if(sess->active && 01134 (replaced || (NAD_AVAL_L(nad, action) == 5 && strncmp("ended", NAD_AVAL(nad, action), NAD_AVAL_L(nad, action)) == 0))) { 01135 01136 sess->bound -= 1; 01137 /* no more resources bound? */ 01138 if(sess->bound < 1){ 01139 sess->active = 0; 01140 01141 if(sess->s) { 01142 /* return the unbind result to the client */ 01143 if(sess->result != NULL) { 01144 sx_nad_write(sess->s, sess->result); 01145 sess->result = NULL; 01146 } 01147 01148 if(replaced) 01149 sx_error(sess->s, stream_err_CONFLICT, NULL); 01150 01151 sx_close(sess->s); 01152 01153 } else { 01154 // handle fake PBX sessions 01155 if(sess->result != NULL) { 01156 nad_free(sess->result); 01157 sess->result = NULL; 01158 } 01159 } 01160 01161 nad_free(nad); 01162 return 0; 01163 } 01164 01165 /* else remove the bound resource */ 01166 if(bres == sess->resources) { 01167 sess->resources = bres->next; 01168 } else { 01169 for(ires = sess->resources; ires != NULL; ires = ires->next) 01170 if(ires->next == bres) 01171 break; 01172 assert(ires != NULL); 01173 ires->next = bres->next; 01174 } 01175 01176 log_write(sess->c2s->log, LOG_NOTICE, "[%d] unbound: jid=%s", sess->s->tag, jid_full(bres->jid)); 01177 01178 jid_free(bres->jid); 01179 free(bres); 01180 01181 /* and return the unbind result to the client */ 01182 if(sess->result != NULL) { 01183 sx_nad_write(sess->s, sess->result); 01184 sess->result = NULL; 01185 } 01186 01187 return 0; 01188 } 01189 01190 id = nad_find_attr(nad, 1, -1, "id", NULL); 01191 01192 /* make sure the id matches */ 01193 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) { 01194 if(id >= 0) { 01195 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); 01196 } else { 01197 log_debug(ZONE, "got a response with no id, but we were expecting %s", bres->sm_request); 01198 } 01199 01200 nad_free(nad); 01201 return 0; 01202 } 01203 01204 /* failed requests */ 01205 if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) { 01206 /* handled request */ 01207 bres->sm_request[0] = '\0'; 01208 01209 /* we only care about failed start and create */ 01210 if((NAD_AVAL_L(nad, action) == 5 && strncmp("start", NAD_AVAL(nad, action), 5) == 0) || 01211 (NAD_AVAL_L(nad, action) == 6 && strncmp("create", NAD_AVAL(nad, action), 6) == 0)) { 01212 01213 /* create failed, so we need to remove them from authreg */ 01214 if(NAD_AVAL_L(nad, action) == 6 && c2s->ar->delete_user != NULL) { 01215 if((c2s->ar->delete_user)(c2s->ar, bres->jid->node, sess->host->realm) != 0) 01216 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); 01217 else 01218 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); 01219 } 01220 01221 /* error the result and return it to the client */ 01222 sx_nad_write(sess->s, stanza_error(sess->result, 0, stanza_err_INTERNAL_SERVER_ERROR)); 01223 sess->result = NULL; 01224 01225 /* remove the bound resource */ 01226 if(bres == sess->resources) { 01227 sess->resources = bres->next; 01228 } else { 01229 for(ires = sess->resources; ires != NULL; ires = ires->next) 01230 if(ires->next == bres) 01231 break; 01232 assert(ires != NULL); 01233 ires->next = bres->next; 01234 } 01235 01236 jid_free(bres->jid); 01237 free(bres); 01238 01239 nad_free(nad); 01240 return 0; 01241 } 01242 01243 log_debug(ZONE, "weird, got a failed session response, with a matching id, but the action is bogus *shrug*"); 01244 01245 nad_free(nad); 01246 return 0; 01247 } 01248 01249 /* session started */ 01250 if(NAD_AVAL_L(nad, action) == 7 && strncmp("started", NAD_AVAL(nad, action), 7) == 0) { 01251 /* handled request */ 01252 bres->sm_request[0] = '\0'; 01253 01254 /* copy the sm id */ 01255 if(smid >= 0) 01256 snprintf(bres->sm_id, sizeof(bres->sm_id), "%.*s", NAD_AVAL_L(nad, smid), NAD_AVAL(nad, smid)); 01257 01258 /* and remember the SM that services us */ 01259 from = nad_find_attr(nad, 0, -1, "from", NULL); 01260 sess->smcomp = malloc(NAD_AVAL_L(nad, from) + 1); 01261 snprintf(sess->smcomp, NAD_AVAL_L(nad, from) + 1, "%.*s", NAD_AVAL_L(nad, from), NAD_AVAL(nad, from)); 01262 01263 nad_free(nad); 01264 01265 /* bring them online, old-skool */ 01266 if(!sess->sasl_authd && sess->s) { 01267 sx_auth(sess->s, "traditional", jid_full(bres->jid)); 01268 return 0; 01269 } 01270 01271 if(sess->result) { 01272 /* return the auth result to the client */ 01273 if(sess->s) sx_nad_write(sess->s, sess->result); 01274 /* or follow-up the session creation with cached presence packet */ 01275 else sm_packet(sess, bres, sess->result); 01276 } 01277 sess->result = NULL; 01278 01279 /* we're good to go */ 01280 sess->active = 1; 01281 01282 return 0; 01283 } 01284 01285 /* handled request */ 01286 bres->sm_request[0] = '\0'; 01287 01288 log_debug(ZONE, "unknown action %.*s", NAD_AVAL_L(nad, id), NAD_AVAL(nad, id)); 01289 01290 nad_free(nad); 01291 01292 return 0; 01293 } 01294 01295 /* client packets */ 01296 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) { 01297 if(!sess->active || !sess->s) { 01298 /* its a strange world .. */ 01299 log_debug(ZONE, "Got packet for %s - dropping", !sess->s ? "session without stream (PBX pipe session?)" : "inactive session"); 01300 nad_free(nad); 01301 return 0; 01302 } 01303 01304 /* sm is bouncing something */ 01305 if(nad_find_attr(nad, 1, ns, "failed", NULL) >= 0) { 01306 if(s) { 01307 /* there's really no graceful way to handle this */ 01308 sx_error(s, stream_err_INTERNAL_SERVER_ERROR, "session manager failed control action"); 01309 sx_close(s); 01310 } 01311 01312 nad_free(nad); 01313 return 0; 01314 } 01315 01316 /* we're counting packets */ 01317 sess->packet_count++; 01318 sess->c2s->packet_count++; 01319 01320 /* remove sm specifics */ 01321 nad_set_attr(nad, 1, ns, "c2s", NULL, 0); 01322 nad_set_attr(nad, 1, ns, "sm", NULL, 0); 01323 01324 /* forget about the internal namespace too */ 01325 if(nad->elems[1].ns == ns) 01326 nad->elems[1].ns = nad->nss[ns].next; 01327 01328 else { 01329 for(scan = nad->elems[1].ns; nad->nss[scan].next != -1 && nad->nss[scan].next != ns; scan = nad->nss[scan].next); 01330 01331 /* got it */ 01332 if(nad->nss[scan].next != -1) 01333 nad->nss[scan].next = nad->nss[ns].next; 01334 } 01335 01336 sx_nad_write_elem(sess->s, nad, 1); 01337 01338 return 0; 01339 } 01340 01341 /* its something else */ 01342 log_debug(ZONE, "unknown packet, dropping"); 01343 01344 nad_free(nad); 01345 return 0; 01346 01347 case event_CLOSED: 01348 mio_close(c2s->mio, c2s->fd); 01349 c2s->fd = NULL; 01350 return -1; 01351 } 01352 01353 return 0; 01354 } 01355 01356 int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { 01357 c2s_t c2s = (c2s_t) arg; 01358 int nbytes; 01359 01360 switch(a) { 01361 case action_READ: 01362 log_debug(ZONE, "read action on fd %d", fd->fd); 01363 01364 ioctl(fd->fd, FIONREAD, &nbytes); 01365 if(nbytes == 0) { 01366 sx_kill(c2s->router); 01367 return 0; 01368 } 01369 01370 return sx_can_read(c2s->router); 01371 01372 case action_WRITE: 01373 log_debug(ZONE, "write action on fd %d", fd->fd); 01374 return sx_can_write(c2s->router); 01375 01376 case action_CLOSE: 01377 log_debug(ZONE, "close action on fd %d", fd->fd); 01378 log_write(c2s->log, LOG_NOTICE, "connection to router closed"); 01379 01380 c2s_lost_router = 1; 01381 01382 /* we're offline */ 01383 c2s->online = 0; 01384 01385 break; 01386 01387 case action_ACCEPT: 01388 break; 01389 } 01390 01391 return 0; 01392 }