jabberd2
2.2.16
|
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 }