jabberd2  2.2.16
sm/sm.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "sm.h"
00022 
00030 sig_atomic_t sm_lost_router = 0;
00031 
00033 int sm_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
00034     sm_t sm = (sm_t) arg;
00035     sx_buf_t buf = (sx_buf_t) data;
00036     sx_error_t *sxe;
00037     nad_t nad;
00038     pkt_t pkt;
00039     int len, ns, elem, attr;
00040     char *domain;
00041 
00042     switch(e) {
00043         case event_WANT_READ:
00044             log_debug(ZONE, "want read");
00045             mio_read(sm->mio, sm->fd);
00046             break;
00047 
00048         case event_WANT_WRITE:
00049             log_debug(ZONE, "want write");
00050             mio_write(sm->mio, sm->fd);
00051             break;
00052 
00053         case event_READ:
00054             log_debug(ZONE, "reading from %d", sm->fd->fd);
00055 
00056             /* do the read */
00057             len = recv(sm->fd->fd, buf->data, buf->len, 0);
00058 
00059             if (len < 0) {
00060                 if (MIO_WOULDBLOCK) {
00061                     buf->len = 0;
00062                     return 0;
00063                 }
00064 
00065                 log_write(sm->log, LOG_NOTICE, "[%d] [router] read error: %s (%d)", sm->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
00066 
00067                 sx_kill(s);
00068                 
00069                 return -1;
00070             }
00071 
00072             else if (len == 0) {
00073                 /* they went away */
00074                 sx_kill(s);
00075 
00076                 return -1;
00077             }
00078 
00079             log_debug(ZONE, "read %d bytes", len);
00080 
00081             buf->len = len;
00082 
00083             return len;
00084 
00085         case event_WRITE:
00086             log_debug(ZONE, "writing to %d", sm->fd->fd);
00087 
00088             len = send(sm->fd->fd, buf->data, buf->len, 0);
00089             if (len >= 0) {
00090                 log_debug(ZONE, "%d bytes written", len);
00091                 return len;
00092             }
00093 
00094             if (MIO_WOULDBLOCK)
00095                 return 0;
00096 
00097             log_write(sm->log, LOG_NOTICE, "[%d] [router] write error: %s (%d)", sm->fd->fd, MIO_STRERROR(MIO_ERROR), MIO_ERROR);
00098 
00099             sx_kill(s);
00100 
00101             return -1;
00102 
00103         case event_ERROR:
00104             sxe = (sx_error_t *) data;
00105             log_write(sm->log, LOG_NOTICE, "error from router: %s (%s)", sxe->generic, sxe->specific);
00106 
00107             if(sxe->code == SX_ERR_AUTH)
00108                 sx_close(s);
00109 
00110             break;
00111 
00112         case event_STREAM:
00113             break;
00114 
00115         case event_OPEN:
00116             log_write(sm->log, LOG_NOTICE, "connection to router established");
00117 
00118             /* set connection attempts counter */
00119             sm->retry_left = sm->retry_lost;
00120 
00121             nad = nad_new();
00122             ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
00123             nad_append_elem(nad, ns, "bind", 0);
00124             nad_append_attr(nad, -1, "name", sm->id);
00125             log_debug(ZONE, "requesting component bind for '%s'", sm->id);
00126             sx_nad_write(sm->router, nad);
00127 
00128             if(xhash_iter_first(sm->hosts))
00129             do {
00130                 xhash_iter_get(sm->hosts, (void *) &domain, &len, NULL);
00131 
00132                 /* skip already requested SM id */
00133                 if (strlen(sm->id) == len && strncmp(sm->id, domain, len) == 0)
00134                     continue;
00135 
00136                 nad = nad_new();
00137                 ns = nad_add_namespace(nad, uri_COMPONENT, NULL);
00138                 elem = nad_append_elem(nad, ns, "bind", 0);
00139                 nad_set_attr(nad, elem, -1, "name", domain, len);
00140                 nad_append_attr(nad, -1, "multi", "to");
00141                 log_debug(ZONE, "requesting domain bind for '%.*s'", len, domain);
00142                 sx_nad_write(sm->router, nad);
00143             
00144             } while(xhash_iter_next(sm->hosts));
00145             break;
00146 
00147         case event_PACKET:
00148             nad = (nad_t) data;
00149 
00150             /* drop unqualified packets */
00151             if (NAD_ENS(nad, 0) < 0) {
00152                 nad_free(nad);
00153                 return 0;
00154             }
00155             /* watch for the features packet */
00156             if (s->state == state_STREAM) {
00157                 if (NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_STREAMS)
00158                     || strncmp(uri_STREAMS, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_STREAMS)) != 0
00159                     || NAD_ENAME_L(nad, 0) != 8 || strncmp("features", NAD_ENAME(nad, 0), 8) != 0) {
00160                     log_debug(ZONE, "got a non-features packet on an unauth'd stream, dropping");
00161                     nad_free(nad);
00162                     return 0;
00163                 }
00164 
00165 #ifdef HAVE_SSL
00166                 /* starttls if we can */
00167                 if (sm->sx_ssl != NULL && s->ssf == 0) {
00168                     ns = nad_find_scoped_namespace(nad, uri_TLS, NULL);
00169                     if (ns >= 0) {
00170                         elem = nad_find_elem(nad, 0, ns, "starttls", 1);
00171                         if (elem >= 0) {
00172                             if (sx_ssl_client_starttls(sm->sx_ssl, s, NULL) == 0) {
00173                                 nad_free(nad);
00174                                 return 0;
00175                             }
00176                             log_write(sm->log, LOG_NOTICE, "unable to establish encrypted session with router");
00177                         }
00178                     }
00179                 }
00180 #endif
00181 
00182                 /* !!! pull the list of mechanisms, and choose the best one.
00183                  *     if there isn't an appropriate one, error and bail */
00184 
00185                 /* authenticate */
00186                 sx_sasl_auth(sm->sx_sasl, s, "jabberd-router", "DIGEST-MD5", sm->router_user, sm->router_pass);
00187 
00188                 nad_free(nad);
00189                 return 0;
00190             }
00191 
00192             /* watch for the bind response */
00193             if (s->state == state_OPEN && !sm->online) {
00194                 if (NAD_NURI_L(nad, NAD_ENS(nad, 0)) != strlen(uri_COMPONENT)
00195                     || strncmp(uri_COMPONENT, NAD_NURI(nad, NAD_ENS(nad, 0)), strlen(uri_COMPONENT)) != 0
00196                     || NAD_ENAME_L(nad, 0) != 4 || strncmp("bind", NAD_ENAME(nad, 0), 4)) {
00197                     log_debug(ZONE, "got a packet from router, but we're not online, dropping");
00198                     nad_free(nad);
00199                     return 0;
00200                 }
00201 
00202                 /* catch errors */
00203                 attr = nad_find_attr(nad, 0, -1, "error", NULL);
00204                 if(attr >= 0) {
00205                     log_write(sm->log, LOG_NOTICE, "router refused bind request (%.*s)", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr));
00206                     exit(1);
00207                 }
00208 
00209                 log_debug(ZONE, "coming online");
00210 
00211                 /* we're online */
00212                 sm->online = sm->started = 1;
00213                 log_write(sm->log, LOG_NOTICE, "%s ready for sessions", sm->id);
00214 
00215                 nad_free(nad);
00216                 return 0;
00217             }
00218 
00219             log_debug(ZONE, "got a packet");
00220 
00221             pkt = pkt_new(sm, nad);
00222             if (pkt == NULL) {
00223                 log_debug(ZONE, "invalid packet, dropping");
00224                 return 0;
00225             }
00226 
00227             /* go */
00228             dispatch(sm, pkt);
00229 
00230             return 0;
00231 
00232         case event_CLOSED:
00233             mio_close(sm->mio, sm->fd);
00234             sm->fd = NULL;
00235             return -1;
00236     }
00237 
00238     return 0;
00239 }
00240 
00241 int sm_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) {
00242     sm_t sm = (sm_t) arg;
00243     int nbytes;
00244 
00245     switch (a) {
00246         case action_READ:
00247             log_debug(ZONE, "read action on fd %d", fd->fd);
00248 
00249             ioctl(fd->fd, FIONREAD, &nbytes);
00250             if(nbytes == 0) {
00251                 sx_kill(sm->router);
00252                 return 0;
00253             }
00254 
00255             return sx_can_read(sm->router);
00256 
00257         case action_WRITE:
00258             log_debug(ZONE, "write action on fd %d", fd->fd);
00259             return sx_can_write(sm->router);
00260 
00261         case action_CLOSE:
00262             log_debug(ZONE, "close action on fd %d", fd->fd);
00263             log_write(sm->log, LOG_NOTICE, "connection to router closed");
00264 
00265             sm_lost_router = 1;
00266 
00267             /* we're offline */
00268             sm->online = 0;
00269 
00270             break;
00271 
00272         case action_ACCEPT:
00273             break;
00274     }
00275 
00276     return 0;
00277 }
00278 
00280 void sm_c2s_action(sess_t dest, char *action, char *target) {
00281     nad_t nad;
00282     int rns, sns;
00283 
00284     nad = nad_new();
00285 
00286     rns = nad_add_namespace(nad, uri_COMPONENT, NULL);
00287     nad_append_elem(nad, rns, "route", 0);
00288 
00289     nad_append_attr(nad, -1, "to", dest->c2s);
00290     nad_append_attr(nad, -1, "from", dest->user->sm->id);
00291 
00292     sns = nad_add_namespace(nad, uri_SESSION, "sc");
00293     nad_append_elem(nad, sns, "session", 1);
00294 
00295     if (dest->c2s_id[0] != '\0')
00296         nad_append_attr(nad, sns, "c2s", dest->c2s_id);
00297     if (dest->sm_id[0] != '\0')
00298         nad_append_attr(nad, sns, "sm", dest->sm_id);
00299 
00300     nad_append_attr(nad, -1, "action", action);
00301     if (target != NULL)
00302         nad_append_attr(nad, -1, "target", target);
00303 
00304     log_debug(ZONE,
00305               "routing nad to %s from %s c2s %s s2s %s action %s target %s",
00306               dest->c2s, dest->user->sm->id, dest->c2s_id, dest->sm_id,
00307               action, target);
00308 
00309     sx_nad_write(dest->user->sm->router, nad);
00310 }
00311 
00313 void sm_signature(sm_t sm, char *str) {
00314     if (sm->siglen == 0) {
00315         snprintf(&sm->signature[sm->siglen], 2048 - sm->siglen, "%s", str);
00316         sm->siglen += strlen(str);
00317     } else {
00318         snprintf(&sm->signature[sm->siglen], 2048 - sm->siglen, " %s", str);
00319         sm->siglen += strlen(str) + 1;
00320     }
00321 }
00322 
00324 int sm_register_ns(sm_t sm, char *uri) {
00325     int ns_idx;
00326 
00327     ns_idx = (int) (long) xhash_get(sm->xmlns, uri);
00328     if (ns_idx == 0) {
00329         ns_idx = xhash_count(sm->xmlns) + 2;
00330         xhash_put(sm->xmlns, pstrdup(xhash_pool(sm->xmlns), uri), (void *) (long) ns_idx);
00331     }
00332     xhash_put(sm->xmlns_refcount, uri, (void *) ((long) xhash_get(sm->xmlns_refcount, uri) + 1));
00333 
00334     return ns_idx;
00335 }
00336 
00338 void sm_unregister_ns(sm_t sm, char *uri) {
00339     int refcount = (int) (long) xhash_get(sm->xmlns_refcount, uri);
00340     if (refcount == 1) {
00341         xhash_zap(sm->xmlns, uri);
00342         xhash_zap(sm->xmlns_refcount, uri);
00343     } else if (refcount > 1) {
00344         xhash_put(sm->xmlns_refcount, uri, (void *) ((long) xhash_get(sm->xmlns_refcount, uri) - 1));
00345     }
00346 }
00347 
00349 int sm_get_ns(sm_t sm, char *uri) {
00350     return (int) (long) xhash_get(sm->xmlns, uri);
00351 }
00352 
00353 // Rate limit check:  Prevent denial-of-service due to excessive database queries
00354 // Make sure owner is responsible for the query!
00355 int sm_storage_rate_limit(sm_t sm, const char *owner) {
00356     rate_t rt;
00357     user_t user;
00358     sess_t sess;
00359     item_t item;
00360 
00361     if (sm->query_rate_total == 0 || owner == NULL)
00362     return FALSE;
00363 
00364     user = xhash_get(sm->users, owner);
00365     if (user != NULL) {
00366         rt = (rate_t) xhash_get(sm->query_rates, owner);
00367         if (rt == NULL) {
00368             rt = rate_new(sm->query_rate_total, sm->query_rate_seconds, sm->query_rate_wait);
00369             xhash_put(sm->query_rates, pstrdup(xhash_pool(sm->query_rates), owner), (void *) rt);
00370             pool_cleanup(xhash_pool(sm->query_rates), (void (*)(void *)) rate_free, rt);
00371         }
00372 
00373         if(rate_check(rt) == 0) {
00374             log_write(sm->log, LOG_WARNING, "[%s] is being disconnected, too many database queries within %d seconds", owner, sm->query_rate_seconds);
00375             user = xhash_get(sm->users, owner);
00376             for (sess = user->sessions; sess != NULL; sess = sess->next) {
00377                 sm_c2s_action(sess, "ended", NULL);
00378             }
00379             if(xhash_iter_first(user->roster))
00380                 do {
00381                     xhash_iter_get(user->roster, NULL, NULL, (void *) &item);
00382                     if(item->to) {
00383                         pkt_router(pkt_create(user->sm, "presence", "unavailable", jid_full(item->jid), jid_full(user->jid)));
00384                     }
00385                 } while(xhash_iter_next(user->roster));
00386             return TRUE;
00387             } else {
00388                 rate_add(rt, 1);
00389             }
00390         } else {
00391             log_debug(ZONE, "Error: could not get user data for %s", owner);
00392     }
00393     return FALSE;
00394 }