1 /*
2 * jabberd - Jabber Open Source Server
3 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4 * Ryan Eatmon, Robert Norris
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 */
20
21 #include "c2s.h"
22
23 #include <stringprep.h>
24 #include <string.h>
25 #include <ctype.h>
26
27 static sig_atomic_t c2s_shutdown = 0;
28 sig_atomic_t c2s_lost_router = 0;
29 static sig_atomic_t c2s_logrotate = 0;
30 static sig_atomic_t c2s_sighup = 0;
31
_c2s_signal(int signum)32 static void _c2s_signal(int signum)
33 {
34 c2s_shutdown = 1;
35 c2s_lost_router = 0;
36 }
37
_c2s_signal_hup(int signum)38 static void _c2s_signal_hup(int signum)
39 {
40 c2s_logrotate = 1;
41 c2s_sighup = 1;
42 }
43
_c2s_signal_usr1(int signum)44 static void _c2s_signal_usr1(int signum)
45 {
46 set_debug_flag(0);
47 }
48
_c2s_signal_usr2(int signum)49 static void _c2s_signal_usr2(int signum)
50 {
51 set_debug_flag(1);
52 }
53
54 /** store the process id */
_c2s_pidfile(c2s_t c2s)55 static void _c2s_pidfile(c2s_t c2s) {
56 const char *pidfile;
57 FILE *f;
58 pid_t pid;
59
60 pidfile = config_get_one(c2s->config, "pidfile", 0);
61 if(pidfile == NULL)
62 return;
63
64 pid = getpid();
65
66 if((f = fopen(pidfile, "w+")) == NULL) {
67 log_write(c2s->log, LOG_ERR, "couldn't open %s for writing: %s", pidfile, strerror(errno));
68 return;
69 }
70
71 if(fprintf(f, "%d", pid) < 0) {
72 log_write(c2s->log, LOG_ERR, "couldn't write to %s: %s", pidfile, strerror(errno));
73 fclose(f);
74 return;
75 }
76
77 fclose(f);
78
79 log_write(c2s->log, LOG_INFO, "process id is %d, written to %s", pid, pidfile);
80 }
81 /** pull values out of the config file */
_c2s_config_expand(c2s_t c2s)82 static void _c2s_config_expand(c2s_t c2s)
83 {
84 const char *str, *ip, *mask;
85 char *req_domain, *to_address, *to_port;
86 config_elem_t elem;
87 int i;
88 stream_redirect_t sr;
89
90 set_debug_log_from_config(c2s->config);
91
92 c2s->id = config_get_one(c2s->config, "id", 0);
93 if(c2s->id == NULL)
94 c2s->id = "c2s";
95
96 c2s->router_ip = config_get_one(c2s->config, "router.ip", 0);
97 if(c2s->router_ip == NULL)
98 c2s->router_ip = "127.0.0.1";
99
100 c2s->router_port = j_atoi(config_get_one(c2s->config, "router.port", 0), 5347);
101
102 c2s->router_user = config_get_one(c2s->config, "router.user", 0);
103 if(c2s->router_user == NULL)
104 c2s->router_user = "jabberd";
105 c2s->router_pass = config_get_one(c2s->config, "router.pass", 0);
106 if(c2s->router_pass == NULL)
107 c2s->router_pass = "secret";
108
109 c2s->router_pemfile = config_get_one(c2s->config, "router.pemfile", 0);
110
111 c2s->router_cachain = config_get_one(c2s->config, "router.cachain", 0);
112
113 c2s->router_private_key_password = config_get_one(c2s->config, "router.private_key_password", 0);
114 c2s->router_ciphers = config_get_one(c2s->config, "router.ciphers", 0);
115
116 c2s->retry_init = j_atoi(config_get_one(c2s->config, "router.retry.init", 0), 3);
117 c2s->retry_lost = j_atoi(config_get_one(c2s->config, "router.retry.lost", 0), 3);
118 if((c2s->retry_sleep = j_atoi(config_get_one(c2s->config, "router.retry.sleep", 0), 2)) < 1)
119 c2s->retry_sleep = 1;
120
121 c2s->log_type = log_STDOUT;
122 if(config_get(c2s->config, "log") != NULL) {
123 if((str = config_get_attr(c2s->config, "log", 0, "type")) != NULL) {
124 if(strcmp(str, "file") == 0)
125 c2s->log_type = log_FILE;
126 else if(strcmp(str, "syslog") == 0)
127 c2s->log_type = log_SYSLOG;
128 }
129 }
130
131 if(c2s->log_type == log_SYSLOG) {
132 c2s->log_facility = config_get_one(c2s->config, "log.facility", 0);
133 c2s->log_ident = config_get_one(c2s->config, "log.ident", 0);
134 if(c2s->log_ident == NULL)
135 c2s->log_ident = "jabberd/c2s";
136 } else if(c2s->log_type == log_FILE)
137 c2s->log_ident = config_get_one(c2s->config, "log.file", 0);
138
139 c2s->packet_stats = config_get_one(c2s->config, "stats.packet", 0);
140
141 c2s->local_ip = config_get_one(c2s->config, "local.ip", 0);
142 if(c2s->local_ip == NULL)
143 c2s->local_ip = "0.0.0.0";
144
145 c2s->local_port = j_atoi(config_get_one(c2s->config, "local.port", 0), 0);
146
147 c2s->local_pemfile = config_get_one(c2s->config, "local.pemfile", 0);
148
149 c2s->local_cachain = config_get_one(c2s->config, "local.cachain", 0);
150
151 c2s->local_private_key_password = config_get_one(c2s->config, "local.private_key_password", 0);
152
153 c2s->local_verify_mode = j_atoi(config_get_one(c2s->config, "local.verify-mode", 0), 0);
154
155 c2s->local_ciphers = config_get_one(c2s->config, "local.ciphers", 0);
156
157 c2s->local_ssl_port = j_atoi(config_get_one(c2s->config, "local.ssl-port", 0), 0);
158
159 c2s->http_forward = config_get_one(c2s->config, "local.httpforward", 0);
160
161 c2s->websocket = (config_get(c2s->config, "io.websocket") != NULL);
162
163 c2s->io_max_fds = j_atoi(config_get_one(c2s->config, "io.max_fds", 0), 1024);
164
165 c2s->compression = (config_get(c2s->config, "io.compression") != NULL);
166
167 c2s->io_check_interval = j_atoi(config_get_one(c2s->config, "io.check.interval", 0), 0);
168 c2s->io_check_idle = j_atoi(config_get_one(c2s->config, "io.check.idle", 0), 0);
169 c2s->io_check_keepalive = j_atoi(config_get_one(c2s->config, "io.check.keepalive", 0), 0);
170
171 c2s->pbx_pipe = config_get_one(c2s->config, "pbx.pipe", 0);
172
173 elem = config_get(c2s->config, "stream_redirect.redirect");
174 if(elem != NULL)
175 {
176 for(i = 0; i < elem->nvalues; i++)
177 {
178 sr = (stream_redirect_t) pmalloco(xhash_pool(c2s->stream_redirects), sizeof(struct stream_redirect_st));
179 if(!sr) {
180 log_write(c2s->log, LOG_ERR, "cannot allocate memory for new stream redirection record, aborting");
181 exit(1);
182 }
183 req_domain = j_attr((const char **) elem->attrs[i], "requested_domain");
184 to_address = j_attr((const char **) elem->attrs[i], "to_address");
185 to_port = j_attr((const char **) elem->attrs[i], "to_port");
186
187 if(req_domain == NULL || to_address == NULL || to_port == NULL) {
188 log_write(c2s->log, LOG_ERR, "Error reading a stream_redirect.redirect element from file, skipping");
189 continue;
190 }
191
192 // Note that to_address should be RFC 3986 compliant
193 sr->to_address = to_address;
194 sr->to_port = to_port;
195
196 xhash_put(c2s->stream_redirects, pstrdup(xhash_pool(c2s->stream_redirects), req_domain), sr);
197 }
198 }
199
200 c2s->ar_module_name = config_get_one(c2s->config, "authreg.module", 0);
201
202 if(config_get(c2s->config, "authreg.mechanisms.traditional.plain") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_PLAIN;
203 if(config_get(c2s->config, "authreg.mechanisms.traditional.digest") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_DIGEST;
204 if(config_get(c2s->config, "authreg.mechanisms.traditional.cram-md5") != NULL) c2s->ar_mechanisms |= AR_MECH_TRAD_CRAMMD5;
205
206 if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.plain") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_PLAIN;
207 if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.digest") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_DIGEST;
208 if(config_get(c2s->config, "authreg.ssl-mechanisms.traditional.cram-md5") != NULL) c2s->ar_ssl_mechanisms |= AR_MECH_TRAD_CRAMMD5;
209
210 elem = config_get(c2s->config, "io.limits.bytes");
211 if(elem != NULL)
212 {
213 c2s->byte_rate_total = j_atoi(elem->values[0], 0);
214 if(c2s->byte_rate_total != 0)
215 {
216 c2s->byte_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 1);
217 c2s->byte_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
218 }
219 }
220
221 elem = config_get(c2s->config, "io.limits.stanzas");
222 if(elem != NULL)
223 {
224 c2s->stanza_rate_total = j_atoi(elem->values[0], 0);
225 if(c2s->stanza_rate_total != 0)
226 {
227 c2s->stanza_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 1);
228 c2s->stanza_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
229 }
230 }
231
232 elem = config_get(c2s->config, "io.limits.connects");
233 if(elem != NULL)
234 {
235 c2s->conn_rate_total = j_atoi(elem->values[0], 0);
236 if(c2s->conn_rate_total != 0)
237 {
238 c2s->conn_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 5);
239 c2s->conn_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5);
240 }
241 }
242
243 c2s->stanza_size_limit = j_atoi(config_get_one(c2s->config, "io.limits.stanzasize", 0), 0);
244
245 /* tweak timed checks with rate times */
246 if(c2s->io_check_interval == 0) {
247 if(c2s->byte_rate_total != 0)
248 c2s->io_check_interval = c2s->byte_rate_wait;
249
250 if(c2s->stanza_rate_total != 0 && c2s->io_check_interval > c2s->stanza_rate_wait)
251 c2s->io_check_interval = c2s->stanza_rate_wait;
252 }
253
254 str = config_get_one(c2s->config, "io.access.order", 0);
255 if(str == NULL || strcmp(str, "deny,allow") != 0)
256 c2s->access = access_new(0);
257 else
258 c2s->access = access_new(1);
259
260 elem = config_get(c2s->config, "io.access.allow");
261 if(elem != NULL)
262 {
263 for(i = 0; i < elem->nvalues; i++)
264 {
265 ip = j_attr((const char **) elem->attrs[i], "ip");
266 mask = j_attr((const char **) elem->attrs[i], "mask");
267
268 if(ip == NULL)
269 continue;
270
271 if(mask == NULL)
272 mask = "255.255.255.255";
273
274 access_allow(c2s->access, ip, mask);
275 }
276 }
277
278 elem = config_get(c2s->config, "io.access.deny");
279 if(elem != NULL)
280 {
281 for(i = 0; i < elem->nvalues; i++)
282 {
283 ip = j_attr((const char **) elem->attrs[i], "ip");
284 mask = j_attr((const char **) elem->attrs[i], "mask");
285
286 if(ip == NULL)
287 continue;
288
289 if(mask == NULL)
290 mask = "255.255.255.255";
291
292 access_deny(c2s->access, ip, mask);
293 }
294 }
295 }
296
_c2s_hosts_expand(c2s_t c2s)297 static void _c2s_hosts_expand(c2s_t c2s)
298 {
299 char *realm;
300 config_elem_t elem;
301 char id[1024];
302 int i;
303
304 elem = config_get(c2s->config, "local.id");
305 if(!elem) {
306 log_write(c2s->log, LOG_NOTICE, "no local.id configured - skipping local domains configuration");
307 return;
308 }
309 for(i = 0; i < elem->nvalues; i++) {
310 host_t host = (host_t) pmalloco(xhash_pool(c2s->hosts), sizeof(struct host_st));
311 if(!host) {
312 log_write(c2s->log, LOG_ERR, "cannot allocate memory for new host, aborting");
313 exit(1);
314 }
315
316 realm = j_attr((const char **) elem->attrs[i], "realm");
317
318 /* stringprep ids (domain names) so that they are in canonical form */
319 strncpy(id, elem->values[i], 1024);
320 id[1023] = '\0';
321 if (stringprep_nameprep(id, 1024) != 0) {
322 log_write(c2s->log, LOG_ERR, "cannot stringprep id %s, aborting", id);
323 exit(1);
324 }
325
326 host->realm = (realm != NULL) ? realm : pstrdup(xhash_pool(c2s->hosts), id);
327
328 host->host_pemfile = j_attr((const char **) elem->attrs[i], "pemfile");
329
330 host->host_cachain = j_attr((const char **) elem->attrs[i], "cachain");
331
332 host->host_verify_mode = j_atoi(j_attr((const char **) elem->attrs[i], "verify-mode"), 0);
333
334 host->host_private_key_password = j_attr((const char **) elem->attrs[i], "private-key-password");
335
336 host->host_ciphers = j_attr((const char **) elem->attrs[i], "ciphers");
337
338 #ifdef HAVE_SSL
339 if(host->host_pemfile != NULL) {
340 if(c2s->sx_ssl == NULL) {
341 c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode, host->host_private_key_password, host->host_ciphers);
342 if(c2s->sx_ssl == NULL) {
343 log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
344 host->host_pemfile = NULL;
345 }
346 } else {
347 if(sx_ssl_server_addcert(c2s->sx_ssl, host->realm, host->host_pemfile, host->host_cachain, host->host_verify_mode, host->host_private_key_password, host->host_ciphers) != 0) {
348 log_write(c2s->log, LOG_ERR, "failed to load %s SSL pemfile", host->realm);
349 host->host_pemfile = NULL;
350 }
351 }
352 }
353 #endif
354
355 host->host_require_starttls = (j_attr((const char **) elem->attrs[i], "require-starttls") != NULL);
356
357 host->ar_module_name = j_attr((const char **) elem->attrs[i], "authreg-module");
358 if(host->ar_module_name) {
359 if((host->ar = authreg_init(c2s, host->ar_module_name)) == NULL) {
360 log_write(c2s->log, LOG_NOTICE, "failed to load %s authreg module - using default", host->realm);
361 host->ar = c2s->ar;
362 }
363 } else
364 host->ar = c2s->ar;
365
366 host->ar_register_enable = (j_attr((const char **) elem->attrs[i], "register-enable") != NULL);
367 host->ar_register_oob = j_attr((const char **) elem->attrs[i], "register-oob");
368 if(host->ar_register_enable || host->ar_register_oob) {
369 host->ar_register_instructions = j_attr((const char **) elem->attrs[i], "instructions");
370 if(host->ar_register_instructions == NULL) {
371 if(host->ar_register_oob)
372 host->ar_register_instructions = "Only web based registration is possible with this server.";
373 else
374 host->ar_register_instructions = "Enter a username and password to register with this server.";
375 }
376 } else
377 host->ar_register_password = (j_attr((const char **) elem->attrs[i], "password-change") != NULL);
378
379 /* check for empty <id/> CDATA - XXX this "1" is VERY config.c dependant !!! */
380 if(! strcmp(id, "1")) {
381 /* remove the realm even if set */
382 host->realm = NULL;
383
384 /* skip if vHost already configured */
385 if(! c2s->vhost)
386 c2s->vhost = host;
387
388 /* add meaningful log "id" */
389 strcpy(id, "default vHost");
390 } else {
391 /* insert into vHosts xhash */
392 xhash_put(c2s->hosts, pstrdup(xhash_pool(c2s->hosts), id), host);
393 }
394
395 log_write(c2s->log, LOG_NOTICE, "[%s] configured; realm=%s, authreg=%s, registration %s, using PEM:%s",
396 id, (host->realm != NULL ? host->realm : "no realm set"),
397 (host->ar_module_name ? host->ar_module_name : c2s->ar_module_name),
398 (host->ar_register_enable ? "enabled" : "disabled"),
399 (host->host_pemfile ? host->host_pemfile : "Default"));
400 }
401 }
402
_c2s_router_connect(c2s_t c2s)403 static int _c2s_router_connect(c2s_t c2s) {
404 log_write(c2s->log, LOG_NOTICE, "attempting connection to router at %s, port=%d", c2s->router_ip, c2s->router_port);
405
406 c2s->fd = mio_connect(c2s->mio, c2s->router_port, c2s->router_ip, NULL, c2s_router_mio_callback, (void *) c2s);
407 if(c2s->fd == NULL) {
408 if(errno == ECONNREFUSED)
409 c2s_lost_router = 1;
410 log_write(c2s->log, LOG_NOTICE, "connection attempt to router failed: %s (%d)", MIO_STRERROR(MIO_ERROR), MIO_ERROR);
411 return 1;
412 }
413
414 c2s->router = sx_new(c2s->sx_env, c2s->fd->fd, c2s_router_sx_callback, (void *) c2s);
415 sx_client_init(c2s->router, 0, NULL, NULL, NULL, "1.0");
416
417 return 0;
418 }
419
_c2s_sx_sasl_callback(int cb,void * arg,void ** res,sx_t s,void * cbarg)420 static int _c2s_sx_sasl_callback(int cb, void *arg, void **res, sx_t s, void *cbarg) {
421 c2s_t c2s = (c2s_t) cbarg;
422 const char *my_realm, *mech;
423 sx_sasl_creds_t creds;
424 static char buf[3072];
425 char mechbuf[256];
426 struct jid_st jid;
427 jid_static_buf jid_buf;
428 int i, r;
429 sess_t sess;
430 char skey[44];
431 host_t host;
432
433 /* init static jid */
434 jid_static(&jid,&jid_buf);
435
436 /* retrieve our session */
437 assert(s != NULL);
438 sprintf(skey, "%d", s->tag);
439
440 /*
441 * Retrieve the session, note that depending on the operation,
442 * session may be null.
443 */
444 sess = xhash_get(c2s->sessions, skey);
445
446 switch(cb) {
447 case sx_sasl_cb_GET_REALM:
448
449 if(s->req_to == NULL) /* this shouldn't happen */
450 my_realm = "";
451
452 else {
453 /* get host for request */
454 host = xhash_get(c2s->hosts, s->req_to);
455 if(host == NULL) {
456 log_write(c2s->log, LOG_ERR, "SASL callback for non-existing host: %s", s->req_to);
457 *res = (void *)NULL;
458 return sx_sasl_ret_FAIL;
459 }
460
461 my_realm = host->realm;
462 if(my_realm == NULL)
463 my_realm = s->req_to;
464 }
465
466 strncpy(buf, my_realm, 256);
467 *res = (void *)buf;
468
469 log_debug(ZONE, "sx sasl callback: get realm: realm is '%s'", buf);
470 return sx_sasl_ret_OK;
471 break;
472
473 case sx_sasl_cb_GET_PASS:
474 assert(sess != NULL);
475 creds = (sx_sasl_creds_t) arg;
476
477 log_debug(ZONE, "sx sasl callback: get pass (authnid=%s, realm=%s)", creds->authnid, creds->realm);
478
479 if(sess->host->ar->get_password && (sess->host->ar->get_password)(
480 sess->host->ar, sess, (char *)creds->authnid, (creds->realm != NULL) ? (char *)creds->realm: "", buf) == 0) {
481 *res = buf;
482 return sx_sasl_ret_OK;
483 }
484
485 return sx_sasl_ret_FAIL;
486
487 case sx_sasl_cb_CHECK_PASS:
488 assert(sess != NULL);
489 creds = (sx_sasl_creds_t) arg;
490
491 log_debug(ZONE, "sx sasl callback: check pass (authnid=%s, realm=%s)", creds->authnid, creds->realm);
492
493 if(sess->host->ar->check_password != NULL) {
494 if ((sess->host->ar->check_password)(
495 sess->host->ar, sess, (char *)creds->authnid, (creds->realm != NULL) ? (char *)creds->realm : "", (char *)creds->pass) == 0)
496 return sx_sasl_ret_OK;
497 else
498 return sx_sasl_ret_FAIL;
499 }
500
501 if(sess->host->ar->get_password != NULL) {
502 if ((sess->host->ar->get_password)(sess->host->ar, sess, (char *)creds->authnid, (creds->realm != NULL) ? (char *)creds->realm : "", buf) != 0)
503 return sx_sasl_ret_FAIL;
504
505 if (strcmp(creds->pass, buf)==0)
506 return sx_sasl_ret_OK;
507 }
508
509 return sx_sasl_ret_FAIL;
510 break;
511
512 case sx_sasl_cb_CHECK_AUTHZID:
513 assert(sess != NULL);
514 creds = (sx_sasl_creds_t) arg;
515
516 /* we need authzid to validate */
517 if(creds->authzid == NULL || creds->authzid[0] == '\0')
518 return sx_sasl_ret_FAIL;
519
520 /* authzid must be a valid jid */
521 if(jid_reset(&jid, creds->authzid, -1) == NULL)
522 return sx_sasl_ret_FAIL;
523
524 /* and have domain == stream to addr */
525 if(!s->req_to || (strcmp(jid.domain, s->req_to) != 0))
526 return sx_sasl_ret_FAIL;
527
528 /* and have no resource */
529 if(jid.resource[0] != '\0')
530 return sx_sasl_ret_FAIL;
531
532 /* and user has right to authorize as */
533 if (sess->host->ar->user_authz_allowed) {
534 if (sess->host->ar->user_authz_allowed(sess->host->ar, sess, (char *)creds->authnid, (char *)creds->realm, (char *)creds->authzid))
535 return sx_sasl_ret_OK;
536 } else {
537 if (strcmp(creds->authnid, jid.node) == 0 &&
538 (sess->host->ar->user_exists)(sess->host->ar, sess, jid.node, jid.domain))
539 return sx_sasl_ret_OK;
540 }
541
542 return sx_sasl_ret_FAIL;
543
544 case sx_sasl_cb_GEN_AUTHZID:
545 /* generate a jid for SASL ANONYMOUS */
546 jid_reset(&jid, s->req_to, -1);
547
548 /* make node a random string */
549 jid_random_part(&jid, jid_NODE);
550
551 strcpy(buf, jid.node);
552
553 *res = (void *)buf;
554
555 return sx_sasl_ret_OK;
556 break;
557
558 case sx_sasl_cb_CHECK_MECH:
559 mech = (char *)arg;
560
561 strncpy(mechbuf, mech, sizeof(mechbuf));
562 mechbuf[sizeof(mechbuf)-1]='\0';
563 for(i = 0; mechbuf[i]; i++) mechbuf[i] = tolower(mechbuf[i]);
564
565 log_debug(ZONE, "sx sasl callback: check mech (mech=%s)", mechbuf);
566
567 /* get host for request */
568 host = xhash_get(c2s->hosts, s->req_to);
569 if(host == NULL) {
570 log_write(c2s->log, LOG_WARNING, "SASL callback for non-existing host: %s", s->req_to);
571 return sx_sasl_ret_FAIL;
572 }
573
574 /* Determine if our configuration will let us use this mechanism.
575 * We support different mechanisms for both SSL and normal use */
576 if (strcmp(mechbuf, "digest-md5") == 0) {
577 /* digest-md5 requires that our authreg support get_password */
578 if (host->ar->get_password == NULL)
579 return sx_sasl_ret_FAIL;
580 } else if (strcmp(mechbuf, "plain") == 0) {
581 /* plain requires either get_password or check_password */
582 if (host->ar->get_password == NULL && host->ar->check_password == NULL)
583 return sx_sasl_ret_FAIL;
584 }
585
586 /* Using SSF is potentially dangerous, as SASL can also set the
587 * SSF of the connection. However, SASL shouldn't do so until after
588 * we've finished mechanism establishment
589 */
590 if (s->ssf>0) {
591 r = snprintf(buf, sizeof(buf), "authreg.ssl-mechanisms.sasl.%s",mechbuf);
592 if (r < -1 || r > sizeof(buf))
593 return sx_sasl_ret_FAIL;
594 if(config_get(c2s->config,buf) != NULL)
595 return sx_sasl_ret_OK;
596 }
597
598 r = snprintf(buf, sizeof(buf), "authreg.mechanisms.sasl.%s",mechbuf);
599 if (r < -1 || r > sizeof(buf))
600 return sx_sasl_ret_FAIL;
601
602 /* Work out if our configuration will let us use this mechanism */
603 if(config_get(c2s->config,buf) != NULL)
604 return sx_sasl_ret_OK;
605 else
606 return sx_sasl_ret_FAIL;
607 default:
608 break;
609 }
610
611 return sx_sasl_ret_FAIL;
612 }
_c2s_time_checks(c2s_t c2s)613 static void _c2s_time_checks(c2s_t c2s) {
614 sess_t sess;
615 time_t now;
616 union xhashv xhv;
617
618 now = time(NULL);
619
620 if(xhash_iter_first(c2s->sessions))
621 do {
622 xhv.sess_val = &sess;
623 xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val);
624
625 if(!sess->s) continue;
626
627 if(c2s->io_check_idle > 0 && now > sess->last_activity + c2s->io_check_idle) {
628 log_write(c2s->log, LOG_NOTICE, "[%d] [%s, port=%d] timed out", sess->fd->fd, sess->ip, sess->port);
629
630 sx_error(sess->s, stream_err_HOST_GONE, "connection timed out");
631 sx_close(sess->s);
632
633 continue;
634 }
635
636 if(c2s->io_check_keepalive > 0 && now > sess->last_activity + c2s->io_check_keepalive && sess->s->state >= state_STREAM) {
637 log_debug(ZONE, "sending keepalive for %d", sess->fd->fd);
638
639 sx_raw_write(sess->s, " ", 1);
640 }
641
642 if(sess->rate != NULL && sess->rate->bad != 0 && rate_check(sess->rate) != 0) {
643 /* read the pending bytes when rate limit is no longer in effect */
644 log_debug(ZONE, "reading throttled %d", sess->fd->fd);
645 sess->s->want_read = 1;
646 sx_can_read(sess->s);
647 }
648
649 } while(xhash_iter_next(c2s->sessions));
650 }
651
_c2s_ar_free(const char * module,int modulelen,void * val,void * arg)652 static void _c2s_ar_free(const char *module, int modulelen, void *val, void *arg) {
653 authreg_t ar = (authreg_t) val;
654 authreg_free(ar);
655 }
656
657 JABBER_MAIN("jabberd2c2s", "Jabber 2 C2S", "Jabber Open Source Server: Client to Server", "jabberd2router\0")
658 {
659 c2s_t c2s;
660 char *config_file;
661 int optchar;
662 int mio_timeout;
663 sess_t sess;
664 bres_t res;
665 union xhashv xhv;
666 time_t check_time = 0;
667 const char *cli_id = 0;
668
669 #ifdef HAVE_UMASK
670 umask((mode_t) 0027);
671 #endif
672
673 srand(time(NULL));
674
675 #ifdef HAVE_WINSOCK2_H
676 /* get winsock running */
677 {
678 WORD wVersionRequested;
679 WSADATA wsaData;
680 int err;
681
682 wVersionRequested = MAKEWORD( 2, 2 );
683
684 err = WSAStartup( wVersionRequested, &wsaData );
685 if ( err != 0 ) {
686 /* !!! tell user that we couldn't find a usable winsock dll */
687 return 0;
688 }
689 }
690 #endif
691
692 jabber_signal(SIGINT, _c2s_signal);
693 jabber_signal(SIGTERM, _c2s_signal);
694 #ifdef SIGHUP
695 jabber_signal(SIGHUP, _c2s_signal_hup);
696 #endif
697 #ifdef SIGPIPE
698 jabber_signal(SIGPIPE, SIG_IGN);
699 #endif
700 jabber_signal(SIGUSR1, _c2s_signal_usr1);
701 jabber_signal(SIGUSR2, _c2s_signal_usr2);
702
703
704 c2s = (c2s_t) calloc(1, sizeof(struct c2s_st));
705
706 /* load our config */
707 c2s->config = config_new();
708
709 config_file = CONFIG_DIR "/c2s.xml";
710
711 /* cmdline parsing */
712 while((optchar = getopt(argc, argv, "Dc:hi:?")) >= 0)
713 {
714 switch(optchar)
715 {
716 case 'c':
717 config_file = optarg;
718 break;
719 case 'D':
720 #ifdef DEBUG
721 set_debug_flag(1);
722 #else
723 printf("WARN: Debugging not enabled. Ignoring -D.\n");
724 #endif
725 break;
726 case 'i':
727 cli_id = optarg;
728 break;
729 case 'h': case '?': default:
730 fputs(
731 "c2s - jabberd client-to-server connector (" VERSION ")\n"
732 "Usage: c2s <options>\n"
733 "Options are:\n"
734 " -c <config> config file to use [default: " CONFIG_DIR "/c2s.xml]\n"
735 " -i id Override <id> config element\n"
736 #ifdef DEBUG
737 " -D Show debug output\n"
738 #endif
739 ,
740 stdout);
741 config_free(c2s->config);
742 free(c2s);
743 return 1;
744 }
745 }
746
747 if(config_load_with_id(c2s->config, config_file, cli_id) != 0)
748 {
749 fputs("c2s: couldn't load config, aborting\n", stderr);
750 config_free(c2s->config);
751 free(c2s);
752 return 2;
753 }
754
755 c2s->stream_redirects = xhash_new(11);
756
757 _c2s_config_expand(c2s);
758
759 c2s->log = log_new(c2s->log_type, c2s->log_ident, c2s->log_facility);
760
761 c2s->ar_modules = xhash_new(5);
762 if(c2s->ar_module_name == NULL) {
763 log_write(c2s->log, LOG_NOTICE, "no default authreg module specified in config file");
764 }
765 else if((c2s->ar = authreg_init(c2s, c2s->ar_module_name)) == NULL) {
766 access_free(c2s->access);
767 config_free(c2s->config);
768 log_free(c2s->log);
769 free(c2s);
770 exit(1);
771 }
772
773 log_write(c2s->log, LOG_NOTICE, "starting up");
774
775 _c2s_pidfile(c2s);
776
777 c2s->sessions = xhash_new(1023);
778
779 c2s->conn_rates = xhash_new(101);
780
781 c2s->dead = jqueue_new();
782
783 c2s->dead_sess = jqueue_new();
784
785 c2s->sx_env = sx_env_new();
786
787 #ifdef HAVE_SSL
788 /* get the ssl context up and running */
789 if(c2s->local_pemfile != NULL) {
790 c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, NULL, c2s->local_pemfile, c2s->local_cachain, c2s->local_verify_mode, c2s->local_private_key_password, c2s->local_ciphers);
791 if(c2s->sx_ssl == NULL) {
792 log_write(c2s->log, LOG_ERR, "failed to load local SSL pemfile, SSL will not be available to clients");
793 c2s->local_pemfile = NULL;
794 }
795 }
796
797 /* try and get something online, so at least we can encrypt to the router */
798 if(c2s->sx_ssl == NULL && c2s->router_pemfile != NULL) {
799 c2s->sx_ssl = sx_env_plugin(c2s->sx_env, sx_ssl_init, NULL, c2s->router_pemfile, c2s->router_cachain, NULL, c2s->router_private_key_password, c2s->router_ciphers);
800 if(c2s->sx_ssl == NULL) {
801 log_write(c2s->log, LOG_ERR, "failed to load router SSL pemfile, channel to router will not be SSL encrypted");
802 c2s->router_pemfile = NULL;
803 }
804 }
805 #endif
806
807 #ifdef USE_WEBSOCKET
808 /* possibly wrap in websocket */
809 if(c2s->websocket) {
810 sx_env_plugin(c2s->sx_env, sx_websocket_init, c2s->http_forward);
811 }
812 #else
813 if(c2s->websocket) {
814 log_write(c2s->log, LOG_ERR, "websocket support not built-in - not enabling");
815 }
816 if(c2s->http_forward) {
817 log_write(c2s->log, LOG_ERR, "httpforward available only with websocket support built-in");
818 }
819 #endif
820
821 #ifdef HAVE_LIBZ
822 /* get compression up and running */
823 if(c2s->compression) {
824 sx_env_plugin(c2s->sx_env, sx_compress_init);
825 }
826 #endif
827
828 /* get stanza ack up */
829 sx_env_plugin(c2s->sx_env, sx_ack_init);
830
831 /* and user IP address plugin */
832 sx_env_plugin(c2s->sx_env, address_init);
833
834 /* get sasl online */
835 c2s->sx_sasl = sx_env_plugin(c2s->sx_env, sx_sasl_init, "xmpp", _c2s_sx_sasl_callback, (void *) c2s);
836 if(c2s->sx_sasl == NULL) {
837 log_write(c2s->log, LOG_ERR, "failed to initialise SASL context, aborting");
838 exit(1);
839 }
840
841 /* get bind up */
842 sx_env_plugin(c2s->sx_env, bind_init, c2s);
843
844 c2s->mio = mio_new(c2s->io_max_fds);
845 if(c2s->mio == NULL) {
846 log_write(c2s->log, LOG_ERR, "failed to create MIO, aborting");
847 exit(1);
848 }
849
850 /* hosts mapping */
851 c2s->hosts = xhash_new(1021);
852 _c2s_hosts_expand(c2s);
853 c2s->sm_avail = xhash_new(1021);
854
855 c2s->retry_left = c2s->retry_init;
856 _c2s_router_connect(c2s);
857
858 mio_timeout = ((c2s->io_check_interval != 0 && c2s->io_check_interval < 5) ?
859 c2s->io_check_interval : 5);
860
861 while(!c2s_shutdown) {
862 mio_run(c2s->mio, mio_timeout);
863
864 if(c2s_logrotate) {
865 set_debug_log_from_config(c2s->config);
866
867 log_write(c2s->log, LOG_NOTICE, "reopening log ...");
868 log_free(c2s->log);
869 c2s->log = log_new(c2s->log_type, c2s->log_ident, c2s->log_facility);
870 log_write(c2s->log, LOG_NOTICE, "log started");
871
872 c2s_logrotate = 0;
873 }
874
875 if(c2s_sighup) {
876 log_write(c2s->log, LOG_NOTICE, "reloading some configuration items ...");
877 config_t conf;
878 conf = config_new();
879 if (conf && config_load(conf, config_file) == 0) {
880 xhash_free(c2s->stream_redirects);
881 c2s->stream_redirects = xhash_new(11);
882
883 char *req_domain, *to_address, *to_port;
884 config_elem_t elem;
885 int i;
886 stream_redirect_t sr;
887
888 elem = config_get(conf, "stream_redirect.redirect");
889 if(elem != NULL)
890 {
891 for(i = 0; i < elem->nvalues; i++)
892 {
893 sr = (stream_redirect_t) pmalloco(xhash_pool(c2s->stream_redirects), sizeof(struct stream_redirect_st));
894 if(!sr) {
895 log_write(c2s->log, LOG_ERR, "cannot allocate memory for new stream redirection record, aborting");
896 exit(1);
897 }
898 req_domain = j_attr((const char **) elem->attrs[i], "requested_domain");
899 to_address = j_attr((const char **) elem->attrs[i], "to_address");
900 to_port = j_attr((const char **) elem->attrs[i], "to_port");
901
902 if(req_domain == NULL || to_address == NULL || to_port == NULL) {
903 log_write(c2s->log, LOG_ERR, "Error reading a stream_redirect.redirect element from file, skipping");
904 continue;
905 }
906
907 // Note that to_address should be RFC 3986 compliant
908 sr->to_address = to_address;
909 sr->to_port = to_port;
910
911 xhash_put(c2s->stream_redirects, pstrdup(xhash_pool(c2s->stream_redirects), req_domain), sr);
912 }
913 }
914 config_free(conf);
915 } else {
916 log_write(c2s->log, LOG_WARNING, "couldn't reload config (%s)", config_file);
917 if (conf) config_free(conf);
918 }
919 c2s_sighup = 0;
920 }
921
922 if(c2s_lost_router) {
923 if(c2s->retry_left < 0) {
924 log_write(c2s->log, LOG_NOTICE, "attempting reconnect");
925 sleep(c2s->retry_sleep);
926 c2s_lost_router = 0;
927 if (c2s->router) sx_free(c2s->router);
928 _c2s_router_connect(c2s);
929 }
930
931 else if(c2s->retry_left == 0) {
932 c2s_shutdown = 1;
933 }
934
935 else {
936 log_write(c2s->log, LOG_NOTICE, "attempting reconnect (%d left)", c2s->retry_left);
937 c2s->retry_left--;
938 sleep(c2s->retry_sleep);
939 c2s_lost_router = 0;
940 if (c2s->router) sx_free(c2s->router);
941 _c2s_router_connect(c2s);
942 }
943 }
944
945 /* cleanup dead sess (before sx_t as sess->result uses sx_t nad cache) */
946 while(jqueue_size(c2s->dead_sess) > 0) {
947 sess = (sess_t) jqueue_pull(c2s->dead_sess);
948
949 /* free sess data */
950 if(sess->ip != NULL) free((void*)sess->ip);
951 if(sess->smcomp != NULL) free((void*)sess->smcomp);
952 if(sess->result != NULL) nad_free(sess->result);
953 if(sess->resources != NULL)
954 for(res = sess->resources; res != NULL;) {
955 bres_t tmp = res->next;
956 jid_free(res->jid);
957 free(res);
958 res = tmp;
959 }
960 if(sess->rate != NULL) rate_free(sess->rate);
961 if(sess->stanza_rate != NULL) rate_free(sess->stanza_rate);
962
963 free(sess);
964 }
965
966 /* cleanup dead sx_ts */
967 while(jqueue_size(c2s->dead) > 0)
968 sx_free((sx_t) jqueue_pull(c2s->dead));
969
970 /* time checks */
971 if(c2s->io_check_interval > 0 && time(NULL) >= c2s->next_check) {
972 log_debug(ZONE, "running time checks");
973
974 _c2s_time_checks(c2s);
975
976 c2s->next_check = time(NULL) + c2s->io_check_interval;
977 log_debug(ZONE, "next time check at %d", c2s->next_check);
978 }
979
980 if(time(NULL) > check_time + 60) {
981 #ifdef POOL_DEBUG
982 pool_stat(1);
983 #endif
984 if(c2s->packet_stats != NULL) {
985 int fd = open(c2s->packet_stats, O_TRUNC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
986 if (fd >= 0) {
987 char buf[100];
988 int len = snprintf(buf, 100, "%lld\n", c2s->packet_count);
989 if (write(fd, buf, len) != len) {
990 close(fd);
991 fd = -1;
992 } else close(fd);
993 }
994 if (fd < 0) {
995 log_write(c2s->log, LOG_ERR, "failed to write packet statistics to: %s", c2s->packet_stats);
996 c2s_shutdown = 1;
997 }
998 }
999
1000 check_time = time(NULL);
1001 }
1002 }
1003
1004 log_write(c2s->log, LOG_NOTICE, "shutting down");
1005
1006 if(xhash_iter_first(c2s->sessions))
1007 do {
1008 xhv.sess_val = &sess;
1009 xhash_iter_get(c2s->sessions, NULL, NULL, xhv.val);
1010
1011 if(sess->active && sess->s)
1012 sx_close(sess->s);
1013
1014 } while(xhash_iter_next(c2s->sessions));
1015
1016 /* cleanup dead sess */
1017 while(jqueue_size(c2s->dead_sess) > 0) {
1018 sess = (sess_t) jqueue_pull(c2s->dead_sess);
1019
1020 /* free sess data */
1021 if(sess->ip != NULL) free((void*)sess->ip);
1022 if(sess->result != NULL) nad_free(sess->result);
1023 if(sess->resources != NULL)
1024 for(res = sess->resources; res != NULL;) {
1025 bres_t tmp = res->next;
1026 jid_free(res->jid);
1027 free(res);
1028 res = tmp;
1029 }
1030
1031 free(sess);
1032 }
1033
1034 while(jqueue_size(c2s->dead) > 0)
1035 sx_free((sx_t) jqueue_pull(c2s->dead));
1036
1037 if (c2s->fd != NULL) mio_close(c2s->mio, c2s->fd);
1038 sx_free(c2s->router);
1039
1040 sx_env_free(c2s->sx_env);
1041
1042 mio_free(c2s->mio);
1043
1044 xhash_free(c2s->sessions);
1045
1046 xhash_walk(c2s->ar_modules, _c2s_ar_free, NULL);
1047 xhash_free(c2s->ar_modules);
1048
1049 xhash_free(c2s->conn_rates);
1050
1051 xhash_free(c2s->stream_redirects);
1052
1053 xhash_free(c2s->sm_avail);
1054
1055 xhash_free(c2s->hosts);
1056
1057 jqueue_free(c2s->dead);
1058
1059 jqueue_free(c2s->dead_sess);
1060
1061 access_free(c2s->access);
1062
1063 log_free(c2s->log);
1064
1065 config_free(c2s->config);
1066
1067 free(c2s);
1068
1069 #ifdef POOL_DEBUG
1070 pool_stat(1);
1071 #endif
1072
1073 #ifdef HAVE_WINSOCK2_H
1074 WSACleanup();
1075 #endif
1076
1077 return 0;
1078 }
1079