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 "router.h" 00022 00023 #define MAX_JID 3072 // node(1023) + '@'(1) + domain(1023) + '/'(1) + resource(1023) + '\0'(1) 00024 #define MAX_MESSAGE 65535 00025 #define SECS_PER_DAY 86400 00026 #define BYTES_PER_MEG 1048576 00027 00029 typedef struct broadcast_st { 00030 router_t r; 00031 component_t src; 00032 nad_t nad; 00033 } *broadcast_t; 00034 00036 static void _router_broadcast(const char *key, int keylen, void *val, void *arg) { 00037 int i; 00038 broadcast_t bc = (broadcast_t) arg; 00039 routes_t routes = (routes_t) val; 00040 00041 for(i = 0; i < routes->ncomp; i++) { 00042 /* I don't care about myself or the elderly (!?) */ 00043 if(routes->comp[i] == bc->src || routes->comp[i]->legacy) 00044 continue; 00045 00046 sx_nad_write(routes->comp[i]->s, nad_copy(bc->nad)); 00047 } 00048 } 00049 00051 static void _router_advertise(router_t r, char *domain, component_t src, int unavail) { 00052 struct broadcast_st bc; 00053 int ns; 00054 00055 log_debug(ZONE, "advertising %s to all routes (unavail=%d)", domain, unavail); 00056 00057 bc.r = r; 00058 bc.src = src; 00059 00060 /* create a new packet */ 00061 bc.nad = nad_new(); 00062 ns = nad_add_namespace(bc.nad, uri_COMPONENT, NULL); 00063 nad_append_elem(bc.nad, ns, "presence", 0); 00064 nad_append_attr(bc.nad, -1, "from", domain); 00065 if(unavail) 00066 nad_append_attr(bc.nad, -1, "type", "unavailable"); 00067 00068 xhash_walk(r->routes, _router_broadcast, (void *) &bc); 00069 00070 nad_free(bc.nad); 00071 } 00072 00074 static void _router_advertise_reverse(const char *key, int keylen, void *val, void *arg) { 00075 component_t dest = (component_t) arg; 00076 routes_t routes = (routes_t) val; 00077 int el, ns, i; 00078 nad_t nad; 00079 00080 assert((int) (routes->name != NULL)); 00081 assert((int) (routes->comp != NULL)); 00082 assert(routes->ncomp); 00083 00084 /* don't tell me about myself */ 00085 for(i = 0; i < routes->ncomp; i++) 00086 if(routes->comp[i] == dest) 00087 return; 00088 00089 log_debug(ZONE, "informing component about %.*s", keylen, key); 00090 00091 /* create a new packet */ 00092 nad = nad_new(); 00093 ns = nad_add_namespace(nad, uri_COMPONENT, NULL); 00094 el = nad_append_elem(nad, ns, "presence", 0); 00095 nad_set_attr(nad, el, -1, "from", key, keylen); 00096 00097 sx_nad_write(dest->s, nad); 00098 } 00099 00100 static void _router_process_handshake(component_t comp, nad_t nad) { 00101 char *hash; 00102 int hashlen; 00103 00104 /* must have a hash as cdata */ 00105 if(NAD_CDATA_L(nad, 0) != 40) { 00106 log_debug(ZONE, "handshake isn't long enough to be a sha1 hash"); 00107 sx_error(comp->s, stream_err_NOT_AUTHORIZED, "handshake isn't long enough to be a sha1 hash"); 00108 sx_close(comp->s); 00109 00110 nad_free(nad); 00111 return; 00112 } 00113 00114 /* make room for shahash_r to work .. needs at least 41 chars */ 00115 hashlen = strlen(comp->s->id) + strlen(comp->r->local_secret) + 1; 00116 if(hashlen < 41) 00117 hashlen = 41; 00118 00119 /* build the creds and hash them */ 00120 hash = (char *) malloc(sizeof(char) * hashlen); 00121 sprintf(hash, "%s%s", comp->s->id, comp->r->local_secret); 00122 shahash_r(hash, hash); 00123 00124 /* check */ 00125 log_debug(ZONE, "checking their hash %.*s against our hash %s", 40, NAD_CDATA(nad, 0), hash); 00126 00127 if(strncmp(hash, NAD_CDATA(nad, 0), 40) == 0) { 00128 log_debug(ZONE, "handshake succeeded"); 00129 00130 free(hash); 00131 00132 /* respond */ 00133 nad->elems[0].icdata = nad->elems[0].itail = -1; 00134 nad->elems[0].lcdata = nad->elems[0].ltail = 0; 00135 sx_nad_write(comp->s, nad); 00136 00137 sx_auth(comp->s, "handshake", comp->s->req_to); 00138 00139 return; 00140 } 00141 00142 log_debug(ZONE, "auth failed"); 00143 00144 free(hash); 00145 00146 /* failed, let them know */ 00147 sx_error(comp->s, stream_err_NOT_AUTHORIZED, "hash didn't match, auth failed"); 00148 sx_close(comp->s); 00149 00150 nad_free(nad); 00151 } 00152 00153 void routes_free(routes_t routes) { 00154 if(routes->name) free(routes->name); 00155 if(routes->comp) free(routes->comp); 00156 free(routes); 00157 } 00158 00159 static int _route_add(xht hroutes, const char *name, component_t comp, route_type_t rtype) { 00160 routes_t routes; 00161 00162 routes = xhash_get(hroutes, name); 00163 if(routes == NULL) { 00164 routes = (routes_t) calloc(1, sizeof(struct routes_st)); 00165 routes->name = strdup(name); 00166 routes->rtype = rtype; 00167 } 00168 routes->comp = (component_t *) realloc(routes->comp, sizeof(component_t *) * (routes->ncomp + 1)); 00169 routes->comp[routes->ncomp] = comp; 00170 routes->ncomp++; 00171 xhash_put(hroutes, routes->name, (void *) routes); 00172 00173 if(routes->rtype != rtype) 00174 log_write(comp->r->log, LOG_ERR, "Mixed route types for '%s' bind request", name); 00175 00176 return routes->ncomp; 00177 } 00178 00179 static void _route_remove(xht hroutes, const char *name, component_t comp) { 00180 routes_t routes; 00181 int i; 00182 00183 routes = xhash_get(hroutes, name); 00184 if(routes == NULL) return; 00185 00186 if(routes->ncomp > 1) { 00187 for(i = 0; i < routes->ncomp; i++) { 00188 if(routes->comp[i] == comp) { 00189 if(i != routes->ncomp - 1) { 00190 routes->comp[i] = routes->comp[routes->ncomp - 1]; 00191 } 00192 routes->ncomp--; 00193 } 00194 } 00195 } 00196 else { 00197 jqueue_push(comp->r->deadroutes, (void *) routes, 0); 00198 xhash_zap(hroutes, name); 00199 } 00200 } 00201 00202 static void _router_process_bind(component_t comp, nad_t nad) { 00203 int attr, multi, n; 00204 jid_t name; 00205 alias_t alias; 00206 char *user, *c; 00207 00208 attr = nad_find_attr(nad, 0, -1, "name", NULL); 00209 if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) { 00210 log_debug(ZONE, "no or invalid 'name' on bind packet, bouncing"); 00211 nad_set_attr(nad, 0, -1, "error", "400", 3); 00212 sx_nad_write(comp->s, nad); 00213 return; 00214 } 00215 00216 user = strdup(comp->s->auth_id); 00217 c = strchr(user, '@'); 00218 if(c != NULL) *c = '\0'; 00219 00220 if(strcmp(user, name->domain) != 0 && !aci_check(comp->r->aci, "bind", user)) { 00221 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but their username (%s) is not permitted to bind other names", comp->ip, comp->port, name->domain, user); 00222 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00223 nad_set_attr(nad, 0, -1, "error", "403", 3); 00224 sx_nad_write(comp->s, nad); 00225 jid_free(name); 00226 free(user); 00227 return; 00228 } 00229 00230 multi = nad_find_attr(nad, 0, -1, "multi", NULL); 00231 if(xhash_get(comp->r->routes, name->domain) != NULL && multi < 0) { 00232 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but it's already bound", comp->ip, comp->port, name->domain); 00233 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00234 nad_set_attr(nad, 0, -1, "error", "409", 3); 00235 sx_nad_write(comp->s, nad); 00236 jid_free(name); 00237 free(user); 00238 return; 00239 } 00240 00241 for(alias = comp->r->aliases; alias != NULL; alias = alias->next) 00242 if(strcmp(alias->name, name->domain) == 0) { 00243 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s', but that name is aliased", comp->ip, comp->port); 00244 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00245 nad_set_attr(nad, 0, -1, "error", "409", 3); 00246 sx_nad_write(comp->s, nad); 00247 jid_free(name); 00248 free(user); 00249 return; 00250 } 00251 00252 /* default route */ 00253 if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "default", 1) >= 0) { 00254 if(!aci_check(comp->r->aci, "default-route", user)) { 00255 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but their username (%s) is not permitted to set a default route", comp->ip, comp->port, name->domain, user); 00256 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00257 nad_set_attr(nad, 0, -1, "error", "403", 3); 00258 sx_nad_write(comp->s, nad); 00259 jid_free(name); 00260 free(user); 00261 return; 00262 } 00263 00264 if(comp->r->default_route != NULL) { 00265 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as the default route, but one already exists", comp->ip, comp->port, name->domain); 00266 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00267 nad_set_attr(nad, 0, -1, "error", "409", 3); 00268 sx_nad_write(comp->s, nad); 00269 jid_free(name); 00270 return; 00271 } 00272 00273 log_write(comp->r->log, LOG_NOTICE, "[%s] set as default route", name->domain); 00274 00275 comp->r->default_route = strdup(name->domain); 00276 } 00277 00278 /* log sinks */ 00279 if(nad_find_elem(nad, 0, NAD_ENS(nad, 0), "log", 1) >= 0) { 00280 if(!aci_check(comp->r->aci, "log", user)) { 00281 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to bind '%s' as a log sink, but their username (%s) is not permitted to do this", comp->ip, comp->port, name->domain, user); 00282 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00283 nad_set_attr(nad, 0, -1, "error", "403", 3); 00284 sx_nad_write(comp->s, nad); 00285 jid_free(name); 00286 free(user); 00287 return; 00288 } 00289 00290 log_write(comp->r->log, LOG_NOTICE, "[%s] set as log sink", name->domain); 00291 00292 xhash_put(comp->r->log_sinks, pstrdup(xhash_pool(comp->r->log_sinks), name->domain), (void *) comp); 00293 } 00294 00295 free(user); 00296 00297 n = _route_add(comp->r->routes, name->domain, comp, multi<0?route_SINGLE:route_MULTI_TO); 00298 xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), name->domain), (void *) comp); 00299 00300 if(n>1) 00301 log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", name->domain, n, comp->ip, comp->port); 00302 else 00303 log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", name->domain, comp->ip, comp->port); 00304 00305 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00306 sx_nad_write(comp->s, nad); 00307 00308 /* advertise name */ 00309 _router_advertise(comp->r, name->domain, comp, 0); 00310 00311 /* tell the new component about everyone else */ 00312 xhash_walk(comp->r->routes, _router_advertise_reverse, (void *) comp); 00313 00314 /* bind aliases */ 00315 for(alias = comp->r->aliases; alias != NULL; alias = alias->next) { 00316 if(strcmp(alias->target, name->domain) == 0) { 00317 _route_add(comp->r->routes, name->domain, comp, route_MULTI_TO); 00318 xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp); 00319 00320 log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, name->domain, comp->ip, comp->port); 00321 00322 /* advertise name */ 00323 _router_advertise(comp->r, alias->name, comp, 0); 00324 } 00325 } 00326 00327 /* done with this */ 00328 jid_free(name); 00329 } 00330 00331 static void _router_process_unbind(component_t comp, nad_t nad) { 00332 int attr; 00333 jid_t name; 00334 00335 attr = nad_find_attr(nad, 0, -1, "name", NULL); 00336 if(attr < 0 || (name = jid_new(NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) { 00337 log_debug(ZONE, "no or invalid 'name' on unbind packet, bouncing"); 00338 nad_set_attr(nad, 0, -1, "error", "400", 3); 00339 sx_nad_write(comp->s, nad); 00340 return; 00341 } 00342 00343 if(xhash_get(comp->routes, name->domain) == NULL) { 00344 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to unbind '%s', but it's not bound to this component", comp->ip, comp->port, name->domain); 00345 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00346 nad_set_attr(nad, 0, -1, "error", "404", 3); 00347 sx_nad_write(comp->s, nad); 00348 jid_free(name); 00349 return; 00350 } 00351 00352 xhash_zap(comp->r->log_sinks, name->domain); 00353 _route_remove(comp->r->routes, name->domain, comp); 00354 xhash_zap(comp->routes, name->domain); 00355 00356 if(comp->r->default_route != NULL && strcmp(comp->r->default_route, name->domain) == 0) { 00357 log_write(comp->r->log, LOG_NOTICE, "[%s] default route offline", name->domain); 00358 free(comp->r->default_route); 00359 comp->r->default_route = NULL; 00360 } 00361 00362 log_write(comp->r->log, LOG_NOTICE, "[%s] offline", name->domain); 00363 00364 nad_set_attr(nad, 0, -1, "name", NULL, 0); 00365 sx_nad_write(comp->s, nad); 00366 00367 /* deadvertise name */ 00368 if(xhash_get(comp->r->routes, name->domain) == NULL) 00369 _router_advertise(comp->r, name->domain, comp, 1); 00370 00371 jid_free(name); 00372 } 00373 00374 static void _router_comp_write(component_t comp, nad_t nad) { 00375 int attr; 00376 00377 if(comp->tq != NULL) { 00378 log_debug(ZONE, "%s port %d is throttled, jqueueing packet", comp->ip, comp->port); 00379 jqueue_push(comp->tq, nad, 0); 00380 return; 00381 } 00382 00383 /* packets go raw to normal components */ 00384 if(!comp->legacy) { 00385 sx_nad_write(comp->s, nad); 00386 return; 00387 } 00388 00389 log_debug(ZONE, "packet for legacy component, munging"); 00390 00391 attr = nad_find_attr(nad, 0, -1, "error", NULL); 00392 if(attr >= 0) { 00393 if(NAD_AVAL_L(nad, attr) == 3 && strncmp("400", NAD_AVAL(nad, attr), 3) == 0) 00394 stanza_error(nad, 1, stanza_err_BAD_REQUEST); 00395 else 00396 stanza_error(nad, 1, stanza_err_SERVICE_UNAVAILABLE); 00397 } 00398 00399 sx_nad_write_elem(comp->s, nad, 1); 00400 } 00401 00402 static void _router_route_log_sink(const char *key, int keylen, void *val, void *arg) { 00403 component_t comp = (component_t) val; 00404 nad_t nad = (nad_t) arg; 00405 00406 log_debug(ZONE, "copying route to '%.*s' (%s, port %d)", keylen, key, comp->ip, comp->port); 00407 00408 nad = nad_copy(nad); 00409 nad_set_attr(nad, 0, -1, "type", "log", 3); 00410 _router_comp_write(comp, nad); 00411 } 00412 00413 static void _router_process_route(component_t comp, nad_t nad) { 00414 int atype, ato, afrom; 00415 unsigned int dest; 00416 struct jid_st sto, sfrom; 00417 jid_static_buf sto_buf, sfrom_buf; 00418 jid_t to = NULL, from = NULL; 00419 routes_t targets; 00420 component_t target; 00421 union xhashv xhv; 00422 00423 /* init static jid */ 00424 jid_static(&sto,&sto_buf); 00425 jid_static(&sfrom,&sfrom_buf); 00426 00427 if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) { 00428 log_debug(ZONE, "dropping error packet, trying to avoid loops"); 00429 nad_free(nad); 00430 return; 00431 } 00432 00433 atype = nad_find_attr(nad, 0, -1, "type", NULL); 00434 ato = nad_find_attr(nad, 0, -1, "to", NULL); 00435 afrom = nad_find_attr(nad, 0, -1, "from", NULL); 00436 00437 if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato)); 00438 if(afrom >= 0) from = jid_reset(&sfrom, NAD_AVAL(nad, afrom), NAD_AVAL_L(nad, afrom)); 00439 00440 /* unicast */ 00441 if(atype < 0) { 00442 if(to == NULL || from == NULL) { 00443 log_debug(ZONE, "unicast route with missing or invalid to or from, bouncing"); 00444 nad_set_attr(nad, 0, -1, "error", "400", 3); 00445 _router_comp_write(comp, nad); 00446 return; 00447 } 00448 00449 log_debug(ZONE, "unicast route from %s to %s", from->domain, to->domain); 00450 00451 /* check the from */ 00452 if(xhash_get(comp->routes, from->domain) == NULL) { 00453 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to send a packet from '%s', but that name is not bound to this component", comp->ip, comp->port, from->domain); 00454 nad_set_attr(nad, 0, -1, "error", "401", 3); 00455 _router_comp_write(comp, nad); 00456 return; 00457 } 00458 00459 /* filter it */ 00460 if(comp->r->filter != NULL) { 00461 int ret = filter_packet(comp->r, nad); 00462 if(ret == stanza_err_REDIRECT) { 00463 ato = nad_find_attr(nad, 0, -1, "to", NULL); 00464 if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato)); 00465 } 00466 else if(ret > 0) { 00467 log_debug(ZONE, "packet filtered out: %s (%s)", _stanza_errors[ret - stanza_err_BAD_REQUEST].name, _stanza_errors[ret - stanza_err_BAD_REQUEST].code); 00468 nad_set_attr(nad, 0, -1, "error", _stanza_errors[ret - stanza_err_BAD_REQUEST].code, 3); 00469 _router_comp_write(comp, nad); 00470 return; 00471 } 00472 } 00473 00474 /* find a target */ 00475 targets = xhash_get(comp->r->routes, to->domain); 00476 if(targets == NULL) { 00477 if(comp->r->default_route != NULL && strcmp(from->domain, comp->r->default_route) == 0) { 00478 log_debug(ZONE, "%s is unbound, bouncing", from->domain); 00479 nad_set_attr(nad, 0, -1, "error", "404", 3); 00480 _router_comp_write(comp, nad); 00481 return; 00482 } 00483 targets = xhash_get(comp->r->routes, comp->r->default_route); 00484 } 00485 00486 if(targets == NULL) { 00487 log_debug(ZONE, "%s is unbound, and no default route, bouncing", to->domain); 00488 nad_set_attr(nad, 0, -1, "error", "404", 3); 00489 _router_comp_write(comp, nad); 00490 return; 00491 } 00492 00493 /* copy to any log sinks */ 00494 if(xhash_count(comp->r->log_sinks) > 0) 00495 xhash_walk(comp->r->log_sinks, _router_route_log_sink, (void *) nad); 00496 00497 /* get route candidate */ 00498 if(targets->ncomp == 1) { 00499 dest = 0; 00500 } 00501 else { 00502 switch(targets->rtype) { 00503 case route_MULTI_TO: 00504 ato = nad_find_attr(nad, 1, -1, "to", NULL); 00505 if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato)); 00506 else { 00507 ato = nad_find_attr(nad, 1, -1, "target", NULL); 00508 if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato)); 00509 else { 00510 char *out; int len; 00511 nad_print(nad, 0, &out, &len); 00512 log_write(comp->r->log, LOG_ERR, "Cannot get destination for multiple route: %.*s", len, out); 00513 } 00514 } 00515 break; 00516 case route_MULTI_FROM: 00517 ato = nad_find_attr(nad, 1, -1, "from", NULL); 00518 if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato)); 00519 else { 00520 char *out; int len; 00521 nad_print(nad, 0, &out, &len); 00522 log_write(comp->r->log, LOG_ERR, "Cannot get source for multiple route: %.*s", len, out); 00523 } 00524 break; 00525 default: 00526 log_write(comp->r->log, LOG_ERR, "Multiple components bound to single component route '%s'", targets->name); 00527 /* simulate no 'to' info in this case */ 00528 } 00529 if(to->node == NULL || strlen(to->node) == 0) { 00530 /* no node in destination JID - going random */ 00531 dest = rand(); 00532 log_debug(ZONE, "randomized to %u %% %d = %d", dest, targets->ncomp, dest % targets->ncomp); 00533 } 00534 else { 00535 /* use JID hash */ 00536 unsigned char hashval[20]; 00537 unsigned int *val; 00538 int i; 00539 00540 shahash_raw(jid_user(to), hashval); 00541 00542 val = (unsigned int *) hashval; 00543 dest = *val; 00544 for(i=1; i < 20 / (sizeof(unsigned int)/sizeof(unsigned char)); i++, val++) { 00545 dest ^= *val; 00546 } 00547 dest >>= 2; 00548 00549 log_debug(ZONE, "JID %s hashed to %u %% %d = %d", jid_user(to), dest, targets->ncomp, dest % targets->ncomp); 00550 00551 /* jid_user() calls jid_expand() which may allocate some memory in _user and _full */ 00552 if (to->_user != NULL ) 00553 free(to->_user); 00554 if (to->_full != NULL ) 00555 free(to->_full); 00556 } 00557 dest = dest % targets->ncomp; 00558 } 00559 00560 target = targets->comp[dest]; 00561 00562 /* push it out */ 00563 log_debug(ZONE, "writing route for '%s'*%u to %s, port %d", to->domain, dest+1, target->ip, target->port); 00564 00565 /* if logging enabled, log messages that match our criteria */ 00566 if (comp->r->message_logging_enabled && comp->r->message_logging_file != NULL) { 00567 int attr_msg_to; 00568 int attr_msg_from; 00569 int attr_route_to; 00570 int attr_route_from; 00571 jid_t jid_msg_from = NULL; 00572 jid_t jid_msg_to = NULL; 00573 jid_t jid_route_from = NULL; 00574 jid_t jid_route_to = NULL; 00575 00576 if ((NAD_ENAME_L(nad, 1) == 7 && strncmp("message", NAD_ENAME(nad, 1), 7) == 0) && // has a "message" element 00577 ((attr_route_from = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0) && 00578 ((attr_route_to = nad_find_attr(nad, 0, -1, "to", NULL)) >= 0) && 00579 ((strncmp(NAD_AVAL(nad, attr_route_to), "c2s", 3)) != 0) && // ignore messages to "c2s" or we'd have dups 00580 ((jid_route_from = jid_new(NAD_AVAL(nad, attr_route_from), NAD_AVAL_L(nad, attr_route_from))) != NULL) && // has valid JID source in route 00581 ((jid_route_to = jid_new(NAD_AVAL(nad, attr_route_to), NAD_AVAL_L(nad, attr_route_to))) != NULL) && // has valid JID destination in route 00582 ((attr_msg_from = nad_find_attr(nad, 1, -1, "from", NULL)) >= 0) && 00583 ((attr_msg_to = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0) && 00584 ((jid_msg_from = jid_new(NAD_AVAL(nad, attr_msg_from), NAD_AVAL_L(nad, attr_msg_from))) != NULL) && // has valid JID source in message 00585 ((jid_msg_to = jid_new(NAD_AVAL(nad, attr_msg_to), NAD_AVAL_L(nad, attr_msg_to))) != NULL)) // has valid JID dest in message 00586 { 00587 message_log(nad, comp->r, jid_full(jid_msg_from), jid_full(jid_msg_to)); 00588 } 00589 if (jid_msg_from != NULL) 00590 jid_free(jid_msg_from); 00591 if (jid_msg_to != NULL) 00592 jid_free(jid_msg_to); 00593 if (jid_route_from != NULL) 00594 jid_free(jid_route_from); 00595 if (jid_route_to != NULL) 00596 jid_free(jid_route_to); 00597 } 00598 00599 _router_comp_write(target, nad); 00600 00601 return; 00602 } 00603 00604 /* broadcast */ 00605 if(NAD_AVAL_L(nad, atype) == 9 && strncmp("broadcast", NAD_AVAL(nad, atype), 9) == 0) { 00606 if(from == NULL) { 00607 log_debug(ZONE, "broadcast route with missing or invalid from, bouncing"); 00608 nad_set_attr(nad, 0, -1, "error", "400", 3); 00609 _router_comp_write(comp, nad); 00610 return; 00611 } 00612 00613 log_debug(ZONE, "broadcast route from %s", from->domain); 00614 00615 /* check the from */ 00616 if(xhash_get(comp->routes, from->domain) == NULL) { 00617 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] tried to send a packet from '%s', but that name is not bound to this component", comp->ip, comp->port, from->domain); 00618 nad_set_attr(nad, 0, -1, "error", "401", 3); 00619 _router_comp_write(comp, nad); 00620 return; 00621 } 00622 00623 /* loop the components and distribute */ 00624 if(xhash_iter_first(comp->r->components)) 00625 do { 00626 xhv.comp_val = ⌖ 00627 xhash_iter_get(comp->r->components, NULL, NULL, xhv.val); 00628 00629 if(target != comp) { 00630 log_debug(ZONE, "writing broadcast to %s, port %d", target->ip, target->port); 00631 00632 _router_comp_write(target, nad_copy(nad)); 00633 } 00634 } while(xhash_iter_next(comp->r->components)); 00635 00636 nad_free(nad); 00637 00638 return; 00639 } 00640 00641 log_debug(ZONE, "unknown route type '%.*s', dropping", NAD_AVAL_L(nad, atype), NAD_AVAL(nad, atype)); 00642 00643 nad_free(nad); 00644 } 00645 00646 static void _router_process_throttle(component_t comp, nad_t nad) { 00647 jqueue_t tq; 00648 nad_t pkt; 00649 00650 if(comp->tq == NULL) { 00651 _router_comp_write(comp, nad); 00652 00653 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] throttling packets on request", comp->ip, comp->port); 00654 comp->tq = jqueue_new(); 00655 } 00656 00657 else { 00658 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] unthrottling packets on request", comp->ip, comp->port); 00659 tq = comp->tq; 00660 comp->tq = NULL; 00661 00662 _router_comp_write(comp, nad); 00663 00664 while((pkt = jqueue_pull(tq)) != NULL) 00665 _router_comp_write(comp, pkt); 00666 00667 jqueue_free(tq); 00668 } 00669 } 00670 00671 static int _router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { 00672 component_t comp = (component_t) arg; 00673 sx_buf_t buf = (sx_buf_t) data; 00674 int rlen, len, attr, ns, sns, n; 00675 sx_error_t *sxe; 00676 nad_t nad; 00677 struct jid_st sto, sfrom; 00678 jid_static_buf sto_buf, sfrom_buf; 00679 jid_t to, from; 00680 alias_t alias; 00681 00682 /* init static jid */ 00683 jid_static(&sto,&sto_buf); 00684 jid_static(&sfrom,&sfrom_buf); 00685 00686 switch(e) { 00687 case event_WANT_READ: 00688 log_debug(ZONE, "want read"); 00689 mio_read(comp->r->mio, comp->fd); 00690 break; 00691 00692 case event_WANT_WRITE: 00693 log_debug(ZONE, "want write"); 00694 mio_write(comp->r->mio, comp->fd); 00695 break; 00696 00697 case event_READ: 00698 log_debug(ZONE, "reading from %d", comp->fd->fd); 00699 00700 /* check rate limits */ 00701 if(comp->rate != NULL) { 00702 if(rate_check(comp->rate) == 0) { 00703 00704 /* inform the app if we haven't already */ 00705 if(!comp->rate_log) { 00706 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] is being byte rate limited", comp->ip, comp->port); 00707 00708 comp->rate_log = 1; 00709 } 00710 00711 log_debug(ZONE, "%d is throttled, delaying read", comp->fd->fd); 00712 00713 buf->len = 0; 00714 return 0; 00715 } 00716 00717 /* find out how much we can have */ 00718 rlen = rate_left(comp->rate); 00719 if(rlen > buf->len) 00720 rlen = buf->len; 00721 } 00722 00723 /* no limit, just read as much as we can */ 00724 else 00725 rlen = buf->len; 00726 00727 /* do the read */ 00728 len = recv(comp->fd->fd, buf->data, rlen, 0); 00729 00730 /* update rate limits */ 00731 if(comp->rate != NULL && len > 0) { 00732 comp->rate_log = 0; 00733 rate_add(comp->rate, len); 00734 } 00735 00736 if(len < 0) { 00737 if(MIO_WOULDBLOCK) { 00738 buf->len = 0; 00739 return 0; 00740 } 00741 00742 log_debug(ZONE, "read failed: %s", strerror(errno)); 00743 00744 sx_kill(comp->s); 00745 00746 return -1; 00747 } 00748 00749 else if(len == 0) { 00750 /* they went away */ 00751 sx_kill(comp->s); 00752 00753 return -1; 00754 } 00755 00756 log_debug(ZONE, "read %d bytes", len); 00757 00758 buf->len = len; 00759 00760 return len; 00761 00762 case event_WRITE: 00763 log_debug(ZONE, "writing to %d", comp->fd->fd); 00764 00765 len = send(comp->fd->fd, buf->data, buf->len, 0); 00766 if(len >= 0) { 00767 log_debug(ZONE, "%d bytes written", len); 00768 return len; 00769 } 00770 00771 if(MIO_WOULDBLOCK) 00772 return 0; 00773 00774 log_debug(ZONE, "write failed: %s", strerror(errno)); 00775 00776 sx_kill(comp->s); 00777 00778 return -1; 00779 00780 case event_ERROR: 00781 sxe = (sx_error_t *) data; 00782 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] error: %s (%s)", comp->ip, comp->port, sxe->generic, sxe->specific); 00783 00784 break; 00785 00786 case event_STREAM: 00787 00788 /* legacy check */ 00789 if(s->ns == NULL || strcmp("jabber:component:accept", s->ns) != 0) 00790 return 0; 00791 00792 /* component, old skool */ 00793 comp->legacy = 1; 00794 00795 /* enabled? */ 00796 if(comp->r->local_secret == NULL) { 00797 sx_error(s, stream_err_INVALID_NAMESPACE, "support for legacy components not available"); /* !!! correct error? */ 00798 sx_close(s); 00799 return 0; 00800 } 00801 00802 /* sanity */ 00803 if(s->req_to == NULL) { 00804 sx_error(s, stream_err_HOST_UNKNOWN, "no 'to' attribute on stream header"); 00805 sx_close(s); 00806 return 0; 00807 } 00808 00809 break; 00810 00811 case event_OPEN: 00812 00813 log_write(comp->r->log, LOG_NOTICE, "[%s, port=%d] authenticated as %s", comp->ip, comp->port, comp->s->auth_id); 00814 00815 /* make a route for legacy components */ 00816 if(comp->legacy) { 00817 for(alias = comp->r->aliases; alias != NULL; alias = alias->next) 00818 if(strcmp(alias->name, s->req_to) == 0) { 00819 sx_error(s, stream_err_HOST_UNKNOWN, "requested name is aliased"); /* !!! correct error? */ 00820 sx_close(s); 00821 return 0; 00822 } 00823 00824 00825 n = _route_add(comp->r->routes, s->req_to, comp, route_MULTI_FROM); 00826 xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), s->req_to), (void *) comp); 00827 00828 if(n>1) 00829 log_write(comp->r->log, LOG_NOTICE, "[%s]:%d online (bound to %s, port %d)", s->req_to, n, comp->ip, comp->port); 00830 else 00831 log_write(comp->r->log, LOG_NOTICE, "[%s] online (bound to %s, port %d)", s->req_to, comp->ip, comp->port); 00832 00833 /* advertise the name */ 00834 _router_advertise(comp->r, s->req_to, comp, 0); 00835 00836 /* this is a legacy component, so we don't tell it about other routes */ 00837 00838 /* bind aliases */ 00839 for(alias = comp->r->aliases; alias != NULL; alias = alias->next) { 00840 if(strcmp(alias->target, s->req_to) == 0) { 00841 _route_add(comp->r->routes, alias->name, comp, route_MULTI_FROM); 00842 xhash_put(comp->routes, pstrdup(xhash_pool(comp->routes), alias->name), (void *) comp); 00843 00844 log_write(comp->r->log, LOG_NOTICE, "[%s] online (alias of '%s', bound to %s, port %d)", alias->name, s->req_to, comp->ip, comp->port); 00845 00846 /* advertise name */ 00847 _router_advertise(comp->r, alias->name, comp, 0); 00848 } 00849 } 00850 } 00851 00852 break; 00853 00854 case event_PACKET: 00855 nad = (nad_t) data; 00856 00857 /* preauth */ 00858 if(comp->s->state == state_STREAM) { 00859 /* non-legacy components can't do anything before auth */ 00860 if(!comp->legacy) { 00861 log_debug(ZONE, "stream is preauth, dropping packet"); 00862 nad_free(nad); 00863 return 0; 00864 } 00865 00866 /* watch for handshake requests */ 00867 if(NAD_ENAME_L(nad, 0) != 9 || strncmp("handshake", NAD_ENAME(nad, 0), NAD_ENAME_L(nad, 0)) != 0) { 00868 log_debug(ZONE, "unknown preauth packet %.*s, dropping", NAD_ENAME_L(nad, 0), NAD_ENAME(nad, 0)); 00869 00870 nad_free(nad); 00871 return 0; 00872 } 00873 00874 /* process incoming handshakes */ 00875 _router_process_handshake(comp, nad); 00876 00877 return 0; 00878 } 00879 00880 /* legacy processing */ 00881 if(comp->legacy) { 00882 log_debug(ZONE, "packet from legacy component, munging it"); 00883 00884 attr = nad_find_attr(nad, 0, -1, "to", NULL); 00885 if(attr < 0 || (to = jid_reset(&sto, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) { 00886 log_debug(ZONE, "invalid or missing 'to' address on legacy packet, dropping it"); 00887 nad_free(nad); 00888 return 0; 00889 } 00890 00891 attr = nad_find_attr(nad, 0, -1, "from", NULL); 00892 if(attr < 0 || (from = jid_reset(&sfrom, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr))) == NULL) { 00893 log_debug(ZONE, "invalid or missing 'from' address on legacy packet, dropping it"); 00894 nad_free(nad); 00895 return 0; 00896 } 00897 00898 /* rewrite component packets into client packets */ 00899 ns = nad_find_namespace(nad, 0, "jabber:component:accept", NULL); 00900 if(ns >= 0) { 00901 if(nad->elems[0].ns == ns) 00902 nad->elems[0].ns = nad->nss[nad->elems[0].ns].next; 00903 else { 00904 for(sns = nad->elems[0].ns; sns >= 0 && nad->nss[sns].next != ns; sns = nad->nss[sns].next); 00905 nad->nss[sns].next = nad->nss[nad->nss[sns].next].next; 00906 } 00907 } 00908 00909 ns = nad_find_namespace(nad, 0, uri_CLIENT, NULL); 00910 if(ns < 0) { 00911 ns = nad_add_namespace(nad, uri_CLIENT, NULL); 00912 nad->scope = -1; 00913 nad->nss[ns].next = nad->elems[0].ns; 00914 nad->elems[0].ns = ns; 00915 } 00916 nad->elems[0].my_ns = ns; 00917 00918 /* wrap up the packet */ 00919 ns = nad_add_namespace(nad, uri_COMPONENT, NULL); 00920 00921 nad_wrap_elem(nad, 0, ns, "route"); 00922 00923 nad_set_attr(nad, 0, -1, "to", to->domain, 0); 00924 nad_set_attr(nad, 0, -1, "from", from->domain, 0); 00925 } 00926 00927 /* top element must be router scoped */ 00928 if(NAD_ENS(nad, 0) < 0 || 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) { 00929 log_debug(ZONE, "invalid packet namespace, dropping"); 00930 nad_free(nad); 00931 return 0; 00932 } 00933 00934 /* bind a name to this component */ 00935 if(NAD_ENAME_L(nad, 0) == 4 && strncmp("bind", NAD_ENAME(nad, 0), 4) == 0) { 00936 _router_process_bind(comp, nad); 00937 return 0; 00938 } 00939 00940 /* unbind a name from this component */ 00941 if(NAD_ENAME_L(nad, 0) == 6 && strncmp("unbind", NAD_ENAME(nad, 0), 6) == 0) { 00942 _router_process_unbind(comp, nad); 00943 return 0; 00944 } 00945 00946 /* route packets */ 00947 if(NAD_ENAME_L(nad, 0) == 5 && strncmp("route", NAD_ENAME(nad, 0), 5) == 0) { 00948 _router_process_route(comp, nad); 00949 return 0; 00950 } 00951 00952 /* throttle packets */ 00953 if(NAD_ENAME_L(nad, 0) == 8 && strncmp("throttle", NAD_ENAME(nad, 0), 8) == 0) { 00954 _router_process_throttle(comp, nad); 00955 return 0; 00956 } 00957 00958 log_debug(ZONE, "unknown packet, dropping"); 00959 00960 nad_free(nad); 00961 return 0; 00962 00963 case event_CLOSED: 00964 { 00965 /* close comp->fd by putting it in closefd ... unless it is already there */ 00966 _jqueue_node_t n; 00967 for (n = comp->r->closefd->front; n != NULL; n = n->prev) 00968 if (n->data == comp->fd) break; 00969 if (!n) jqueue_push(comp->r->closefd, (void *) comp->fd, 0 /*priority*/); 00970 return 0; 00971 } 00972 } 00973 00974 return 0; 00975 } 00976 00977 static int _router_accept_check(router_t r, mio_fd_t fd, char *ip) { 00978 rate_t rt; 00979 00980 if(access_check(r->access, ip) == 0) { 00981 log_write(r->log, LOG_NOTICE, "[%d] [%s] access denied by configuration", fd->fd, ip); 00982 return 1; 00983 } 00984 00985 if(r->conn_rate_total != 0) { 00986 rt = (rate_t) xhash_get(r->conn_rates, ip); 00987 if(rt == NULL) { 00988 rt = rate_new(r->conn_rate_total, r->conn_rate_seconds, r->conn_rate_wait); 00989 xhash_put(r->conn_rates, pstrdup(xhash_pool(r->conn_rates), ip), (void *) rt); 00990 } 00991 00992 if(rate_check(rt) == 0) { 00993 log_write(r->log, LOG_NOTICE, "[%d] [%s] is being rate limited", fd->fd, ip); 00994 return 1; 00995 } 00996 00997 rate_add(rt, 1); 00998 } 00999 01000 return 0; 01001 } 01002 01003 static void _router_route_unbind_walker(const char *key, int keylen, void *val, void *arg) { 01004 component_t comp = (component_t) arg; 01005 01006 char * local_key; 01007 xhash_zapx(comp->r->log_sinks, key, keylen); 01008 local_key = (char *) malloc(keylen + 1); 01009 memcpy(local_key, key, keylen); 01010 local_key[keylen] = 0; 01011 _route_remove(comp->r->routes, local_key, comp); 01012 xhash_zapx(comp->routes, key, keylen); 01013 01014 if(comp->r->default_route != NULL && strlen(comp->r->default_route) == keylen && strncmp(key, comp->r->default_route, keylen) == 0) { 01015 log_write(comp->r->log, LOG_NOTICE, "[%.*s] default route offline", keylen, key); 01016 free(comp->r->default_route); 01017 comp->r->default_route = NULL; 01018 } 01019 01020 log_write(comp->r->log, LOG_NOTICE, "[%.*s] offline", keylen, key); 01021 01022 /* deadvertise name */ 01023 if(xhash_getx(comp->r->routes, key, keylen) == NULL) 01024 _router_advertise(comp->r, local_key, comp, 1); 01025 free(local_key); 01026 } 01027 01028 int router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg) { 01029 component_t comp = (component_t) arg; 01030 router_t r = (router_t) arg; 01031 struct sockaddr_storage sa; 01032 int namelen = sizeof(sa), port, nbytes; 01033 01034 switch(a) { 01035 case action_READ: 01036 log_debug(ZONE, "read action on fd %d", fd->fd); 01037 01038 /* they did something */ 01039 comp->last_activity = time(NULL); 01040 01041 ioctl(fd->fd, FIONREAD, &nbytes); 01042 if(nbytes == 0) { 01043 sx_kill(comp->s); 01044 return 0; 01045 } 01046 01047 return sx_can_read(comp->s); 01048 01049 case action_WRITE: 01050 log_debug(ZONE, "write action on fd %d", fd->fd); 01051 01052 /* update activity timestamp */ 01053 comp->last_activity = time(NULL); 01054 01055 return sx_can_write(comp->s); 01056 01057 case action_CLOSE: 01058 log_debug(ZONE, "close action on fd %d", fd->fd); 01059 01060 r = comp->r; 01061 01062 log_write(r->log, LOG_NOTICE, "[%s, port=%d] disconnect", comp->ip, comp->port); 01063 01064 /* unbind names */ 01065 xhash_walk(comp->routes, _router_route_unbind_walker, (void *) comp); 01066 01067 /* deregister component */ 01068 xhash_zap(r->components, comp->ipport); 01069 01070 xhash_free(comp->routes); 01071 01072 if(comp->tq != NULL) 01073 /* !!! bounce packets */ 01074 jqueue_free(comp->tq); 01075 01076 rate_free(comp->rate); 01077 01078 jqueue_push(comp->r->dead, (void *) comp->s, 0); 01079 01080 free(comp); 01081 01082 break; 01083 01084 case action_ACCEPT: 01085 log_debug(ZONE, "accept action on fd %d", fd->fd); 01086 01087 getpeername(fd->fd, (struct sockaddr *) &sa, &namelen); 01088 port = j_inet_getport(&sa); 01089 01090 log_write(r->log, LOG_NOTICE, "[%s, port=%d] connect", (char *) data, port); 01091 01092 if(_router_accept_check(r, fd, (char *) data) != 0) 01093 return 1; 01094 01095 comp = (component_t) calloc(1, sizeof(struct component_st)); 01096 01097 comp->r = r; 01098 01099 comp->fd = fd; 01100 01101 snprintf(comp->ip, INET6_ADDRSTRLEN, "%s", (char *) data); 01102 comp->port = port; 01103 01104 snprintf(comp->ipport, INET6_ADDRSTRLEN, "%s:%d", comp->ip, comp->port); 01105 01106 comp->s = sx_new(r->sx_env, fd->fd, _router_sx_callback, (void *) comp); 01107 mio_app(m, fd, router_mio_callback, (void *) comp); 01108 01109 if(r->byte_rate_total != 0) 01110 comp->rate = rate_new(r->byte_rate_total, r->byte_rate_seconds, r->byte_rate_wait); 01111 01112 comp->routes = xhash_new(51); 01113 01114 /* register component */ 01115 log_debug(ZONE, "new component (%p) \"%s\"", comp, comp->ipport); 01116 xhash_put(r->components, comp->ipport, (void *) comp); 01117 01118 #ifdef HAVE_SSL 01119 sx_server_init(comp->s, SX_SSL_STARTTLS_OFFER | SX_SASL_OFFER); 01120 #else 01121 sx_server_init(comp->s, SX_SASL_OFFER); 01122 #endif 01123 01124 break; 01125 } 01126 01127 return 0; 01128 } 01129 01130 01131 int message_log(nad_t nad, router_t r, const unsigned char *msg_from, const unsigned char *msg_to) 01132 { 01133 time_t t; 01134 char *time_pos; 01135 int time_sz; 01136 struct stat filestat; 01137 FILE *message_file; 01138 short int new_msg_file = 0; 01139 int i; 01140 int nad_body_len = 0; 01141 long int nad_body_start = 0; 01142 int body_count; 01143 char *nad_body = NULL; 01144 char body[MAX_MESSAGE*2]; 01145 01146 assert((int) (nad != NULL)); 01147 01148 /* timestamp */ 01149 t = time(NULL); 01150 time_pos = ctime(&t); 01151 time_sz = strlen(time_pos); 01152 /* chop off the \n */ 01153 time_pos[time_sz-1]=' '; 01154 01155 // Find the message body 01156 for (i = 0; NAD_ENAME_L(nad, i) > 0; i++) 01157 { 01158 if((NAD_ENAME_L(nad, i) == 4) && (strncmp("body", NAD_ENAME(nad, i), 4) == 0)) 01159 { 01160 nad_body_len = NAD_CDATA_L(nad, i); 01161 if (nad_body_len > 0) { 01162 nad_body = NAD_CDATA(nad, i); 01163 } else { 01164 log_write(r->log, LOG_NOTICE, "message_log received a message with empty body"); 01165 return 0; 01166 } 01167 break; 01168 } 01169 } 01170 01171 // Don't log anything if we found no NAD body 01172 if (nad_body == NULL) { 01173 return 0; 01174 } 01175 01176 // Store original pointer address so that we know when to stop iterating through nad_body 01177 nad_body_start = nad_body; 01178 01179 // replace line endings with "\n" 01180 for (body_count = 0; (nad_body < nad_body_start + nad_body_len) && (body_count < (MAX_MESSAGE*2)-3); nad_body++) { 01181 if (*nad_body == '\n') { 01182 body[body_count++] = '\\'; 01183 body[body_count++] = 'n'; 01184 } else { 01185 body[body_count++] = *nad_body; 01186 } 01187 } 01188 body[body_count] = '\0'; 01189 01190 // Log our message 01191 umask((mode_t) 0077); 01192 if (stat(r->message_logging_file, &filestat)) { 01193 new_msg_file = 1; 01194 } 01195 01196 if ((message_file = fopen(r->message_logging_file, "a")) == NULL) 01197 { 01198 log_write(r->log, LOG_ERR, "Unable to open message log for writing: %s", strerror(errno)); 01199 return 1; 01200 } 01201 01202 if (new_msg_file) { 01203 if (! fprintf(message_file, "# This message log is created by the jabberd router.\n")) 01204 { 01205 log_write(r->log, LOG_ERR, "Unable to write to message log: %s", strerror(errno)); 01206 return 1; 01207 } 01208 fprintf(message_file, "# See router.xml for logging options.\n"); 01209 fprintf(message_file, "# Format: (Date)<tab>(From JID)<tab>(To JID)<tab>(Message Body)<line end>\n"); 01210 } 01211 01212 if (! fprintf(message_file, "%s\t%s\t%s\t%s\n", time_pos, msg_from, msg_to, body)) 01213 { 01214 log_write(r->log, LOG_ERR, "Unable to write to message log: %s", strerror(errno)); 01215 return 1; 01216 } 01217 01218 fclose(message_file); 01219 01220 return 0; 01221 }