23 #include <stringprep.h> 66 if((f = fopen(pidfile,
"w+")) == NULL) {
67 log_write(c2s->
log, LOG_ERR,
"couldn't open %s for writing: %s", pidfile, strerror(errno));
71 if(fprintf(f,
"%d", pid) < 0) {
72 log_write(c2s->
log, LOG_ERR,
"couldn't write to %s: %s", pidfile, strerror(errno));
79 log_write(c2s->
log, LOG_INFO,
"process id is %d, written to %s", pid, pidfile);
84 const char *str, *ip, *mask;
85 char *req_domain, *to_address, *to_port;
124 if(strcmp(str,
"file") == 0)
126 else if(strcmp(str,
"syslog") == 0)
176 for(i = 0; i < elem->
nvalues; i++)
180 log_write(c2s->
log, LOG_ERR,
"cannot allocate memory for new stream redirection record, aborting");
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");
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");
255 if(str == NULL || strcmp(str,
"deny,allow") != 0)
263 for(i = 0; i < elem->
nvalues; i++)
266 mask =
j_attr((
const char **) elem->
attrs[i],
"mask");
272 mask =
"255.255.255.255";
281 for(i = 0; i < elem->
nvalues; i++)
284 mask =
j_attr((
const char **) elem->
attrs[i],
"mask");
290 mask =
"255.255.255.255";
306 log_write(c2s->
log, LOG_NOTICE,
"no local.id configured - skipping local domains configuration");
309 for(i = 0; i < elem->
nvalues; i++) {
312 log_write(c2s->
log, LOG_ERR,
"cannot allocate memory for new host, aborting");
316 realm =
j_attr((
const char **) elem->
attrs[i],
"realm");
319 strncpy(
id, elem->
values[i], 1024);
321 if (stringprep_nameprep(
id, 1024) != 0) {
322 log_write(c2s->
log, LOG_ERR,
"cannot stringprep id %s, aborting",
id);
360 log_write(c2s->
log, LOG_NOTICE,
"failed to load %s authreg module - using default", host->
realm);
380 if(! strcmp(
id,
"1")) {
389 strcpy(
id,
"default vHost");
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"),
407 if(c2s->fd == NULL) {
408 if(errno == ECONNREFUSED)
422 const char *my_realm, *mech;
424 static char buf[3072];
438 sprintf(skey,
"%d", s->
tag);
461 my_realm = host->
realm;
466 strncpy(buf, my_realm, 256);
469 log_debug(
ZONE,
"sx sasl callback: get realm: realm is '%s'", buf);
474 assert(sess != NULL);
488 assert(sess != NULL);
505 if (strcmp(creds->
pass, buf)==0)
513 assert(sess != NULL);
551 strcpy(buf, jid.
node);
561 strncpy(mechbuf, mech,
sizeof(mechbuf));
562 mechbuf[
sizeof(mechbuf)-1]=
'\0';
563 for(i = 0; mechbuf[i]; i++) mechbuf[i] = tolower(mechbuf[i]);
565 log_debug(
ZONE,
"sx sasl callback: check mech (mech=%s)", mechbuf);
570 log_write(c2s->
log, LOG_WARNING,
"SASL callback for non-existing host: %s", s->
req_to);
576 if (strcmp(mechbuf,
"digest-md5") == 0) {
580 }
else if (strcmp(mechbuf,
"plain") == 0) {
591 r = snprintf(buf,
sizeof(buf),
"authreg.ssl-mechanisms.sasl.%s",mechbuf);
592 if (r < -1 || r >
sizeof(buf))
598 r = snprintf(buf,
sizeof(buf),
"authreg.mechanisms.sasl.%s",mechbuf);
599 if (r < -1 || r >
sizeof(buf))
625 if(!sess->
s)
continue;
657 JABBER_MAIN(
"jabberd2c2s",
"Jabber 2 C2S",
"Jabber Open Source Server: Client to Server",
"jabberd2router\0")
666 time_t check_time = 0;
667 const char *cli_id = 0;
670 umask((mode_t) 0027);
675 #ifdef HAVE_WINSOCK2_H 678 WORD wVersionRequested;
682 wVersionRequested = MAKEWORD( 2, 2 );
684 err = WSAStartup( wVersionRequested, &wsaData );
709 config_file = CONFIG_DIR
"/c2s.xml";
712 while((optchar = getopt(argc, argv,
"Dc:hi:?")) >= 0)
717 config_file = optarg;
723 printf(
"WARN: Debugging not enabled. Ignoring -D.\n");
729 case 'h':
case '?':
default:
731 "c2s - jabberd client-to-server connector (" VERSION
")\n" 732 "Usage: c2s <options>\n" 734 " -c <config> config file to use [default: " CONFIG_DIR
"/c2s.xml]\n" 735 " -i id Override <id> config element\n" 737 " -D Show debug output\n" 749 fputs(
"c2s: couldn't load config, aborting\n", stderr);
763 log_write(c2s->
log, LOG_NOTICE,
"no default authreg module specified in config file");
792 log_write(c2s->
log, LOG_ERR,
"failed to load local SSL pemfile, SSL will not be available to clients");
801 log_write(c2s->
log, LOG_ERR,
"failed to load router SSL pemfile, channel to router will not be SSL encrypted");
814 log_write(c2s->
log, LOG_ERR,
"websocket support not built-in - not enabling");
817 log_write(c2s->
log, LOG_ERR,
"httpforward available only with websocket support built-in");
836 if(c2s->sx_sasl == NULL) {
837 log_write(c2s->log, LOG_ERR,
"failed to initialise SASL context, aborting");
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");
855 c2s->retry_left = c2s->retry_init;
858 mio_timeout = ((c2s->io_check_interval != 0 && c2s->io_check_interval < 5) ?
859 c2s->io_check_interval : 5);
862 mio_run(c2s->mio, mio_timeout);
867 log_write(c2s->log, LOG_NOTICE,
"reopening log ...");
869 c2s->log =
log_new(c2s->log_type, c2s->log_ident, c2s->log_facility);
870 log_write(c2s->log, LOG_NOTICE,
"log started");
876 log_write(c2s->log, LOG_NOTICE,
"reloading some configuration items ...");
883 char *req_domain, *to_address, *to_port;
888 elem =
config_get(conf,
"stream_redirect.redirect");
891 for(i = 0; i < elem->
nvalues; i++)
895 log_write(c2s->log, LOG_ERR,
"cannot allocate memory for new stream redirection record, aborting");
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");
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");
916 log_write(c2s->log, LOG_WARNING,
"couldn't reload config (%s)", config_file);
923 if(c2s->retry_left < 0) {
924 log_write(c2s->log, LOG_NOTICE,
"attempting reconnect");
925 sleep(c2s->retry_sleep);
927 if (c2s->router)
sx_free(c2s->router);
931 else if(c2s->retry_left == 0) {
936 log_write(c2s->log, LOG_NOTICE,
"attempting reconnect (%d left)", c2s->retry_left);
938 sleep(c2s->retry_sleep);
940 if (c2s->router)
sx_free(c2s->router);
950 if(sess->
ip != NULL) free((
void*)sess->
ip);
954 for(res = sess->
resources; res != NULL;) {
971 if(c2s->io_check_interval > 0 && time(NULL) >= c2s->next_check) {
976 c2s->next_check = time(NULL) + c2s->io_check_interval;
980 if(time(NULL) > check_time + 60) {
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);
988 int len = snprintf(buf, 100,
"%lld\n", c2s->packet_count);
989 if (write(fd, buf, len) != len) {
995 log_write(c2s->log, LOG_ERR,
"failed to write packet statistics to: %s", c2s->packet_stats);
1000 check_time = time(NULL);
1004 log_write(c2s->log, LOG_NOTICE,
"shutting down");
1021 if(sess->
ip != NULL) free((
void*)sess->
ip);
1024 for(res = sess->
resources; res != NULL;) {
1037 if (c2s->fd != NULL)
mio_close(c2s->mio, c2s->fd);
1073 #ifdef HAVE_WINSOCK2_H int(* check_password)(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[257])
check the given password against the stored password, 0 if equal, !0 if not equal (password auth) ...
int address_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
int io_check_interval
time checks
jid_t jid_reset(jid_t jid, const char *id, int len)
build a jid from an id
#define sx_sasl_cb_CHECK_MECH
static void _c2s_signal_hup(int signum)
struct stream_redirect_st * stream_redirect_t
const char * log_facility
int access_deny(access_t access, const char *ip, const char *mask)
int config_load_with_id(config_t c, const char *file, const char *id)
turn an xml file into a config hash
static int _c2s_sx_sasl_callback(int cb, void *arg, void **res, sx_t s, void *cbarg)
const char * http_forward
http forwarding URL
xht ar_modules
loaded auth/reg modules
static void _c2s_pidfile(c2s_t c2s)
store the process id
int ar_register_enable
registration
int sx_ack_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
void config_free(config_t c)
cleanup
access_t access
access controls
int(* get_password)(authreg_t ar, sess_t sess, const char *username, const char *realm, char password[257])
return this users cleartext password in the array (digest auth, password auth)
mio_t mio_new(int maxfd)
create/free the mio subsytem
access_t access_new(int order)
#define mio_run(m, timeout)
give some cpu time to mio to check it's sockets, 0 is non-blocking
void jid_static(jid_t jid, jid_static_buf *buf)
Make jid to use static buffer (jid data won't be allocated dynamically, but given buffer will be alwa...
const char * router_ciphers
int jqueue_size(jqueue_t q)
int(* user_exists)(authreg_t ar, sess_t sess, const char *username, const char *realm)
returns 1 if the user exists, 0 if not
const char * host_ciphers
list of TLS ciphers
int compression
enable Stream Compression
void log_write(log_t log, int level, const char *msgfmt,...)
static void _c2s_time_checks(c2s_t c2s)
#define AR_MECH_TRAD_DIGEST
sx_t sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg)
if you change these, reflect your changes in the table in error.c
config_t config_new(void)
new config structure
int sx_ssl_server_addcert(sx_plugin_t p, const char *name, const char *pemfile, const char *cachain, int mode, const char *password, const char *ciphers)
args: name, pemfile, cachain, mode
list of resources bound to session
int io_max_fds
max file descriptors
static char * config_file
char * host_private_key_password
private key password
int ar_mechanisms
allowed mechanisms
holder for the config hash and nad
static void _c2s_config_expand(c2s_t c2s)
pull values out of the config file
void sx_raw_write(sx_t s, const char *buf, int len)
app version
const char * id
our id (hostname) with the router
int j_atoi(const char *a, int def)
int host_verify_mode
verify-mode
int bind_init(sx_env_t env, sx_plugin_t p, va_list args)
plugin initialiser
void nad_free(nad_t nad)
free that nad
int stanza_size_limit
maximum stanza size
int xhash_iter_next(xht h)
void jid_random_part(jid_t jid, jid_part_t part)
create random resource
static void _c2s_signal(int signum)
sx_env_t sx_env_new(void)
#define mio_connect(m, port, hostip, srcip, app, arg)
for creating a new socket connected to this ip:port (returns new fd or <0, use mio_read/write first) ...
#define AR_MECH_TRAD_CRAMMD5
#define AR_MECH_TRAD_PLAIN
void rate_free(rate_t rt)
const char * router_pemfile
char * config_get_attr(config_t c, const char *key, int num, const char *attr)
get an attr for this value
void jqueue_free(jqueue_t q)
const char * router_cachain
static void _c2s_signal_usr2(int signum)
const char * router_ip
how to connect to the router
static void _c2s_signal_usr1(int signum)
const char * local_ip
ip to listen on
void access_free(access_t access)
#define MIO_ERROR
all MIO related routines should use those for error reporting
int(* user_authz_allowed)(authreg_t ar, sess_t sess, const char *username, const char *realm, const char *requested_user)
returns 1 if the user is permitted to authorize as the requested_user, 0 if not.
const char * router_private_key_password
int sx_can_read(sx_t s)
we can read
#define sx_sasl_cb_CHECK_AUTHZID
sx_plugin_t sx_env_plugin(sx_env_t env, sx_plugin_init_t init,...)
load a plugin into the environment
holds the state for a single stream
const char * ar_register_instructions
char jid_static_buf[3 *1025]
JID static buffer.
void * pmalloco(pool_t p, int size)
easy safety utility (for creating blank mem for structs, etc)
void sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version)
void set_debug_log_from_config(config_t c)
void jid_free(jid_t jid)
free a jid
const char * realm
our realm (SASL)
void xhash_put(xht h, const char *key, void *val)
struct sx_sasl_creds_st * sx_sasl_creds_t
host_t host
host this session belongs to
int local_verify_mode
verify-mode
int local_port
unencrypted port
#define stream_err_HOST_GONE
int xhash_iter_get(xht h, const char **key, int *keylen, void **val)
const char * host_pemfile
starttls pemfile
int conn_rate_total
connection rates
int c2s_router_sx_callback(sx_t s, sx_event_t e, void *data, void *arg)
JABBER_MAIN("jabberd2c2s", "Jabber 2 C2S", "Jabber Open Source Server: Client to Server", "jabberd2router\)
struct authreg_st * authreg_t
jsighandler_t * jabber_signal(int signo, jsighandler_t *func)
sx_env_t sx_env
sx environment
int retry_init
connect retry
static int _c2s_router_connect(c2s_t c2s)
int rate_check(rate_t rt)
const char * ar_module_name
void sx_error(sx_t s, int err, const char *text)
xht stream_redirects
stream redirection (see-other-host) on session connect
JABBERD2_API int sx_sasl_init(sx_env_t env, sx_plugin_t p, va_list args)
init function
log_type_t log_type
log data
config_elem_t config_get(config_t c, const char *key)
get the config element for this key
jqueue_t dead_sess
list of sess on the way out
#define sx_sasl_cb_GET_REALM
There is one instance of this struct per user who is logged in to this c2s instance.
void * jqueue_pull(jqueue_t q)
int xhash_iter_first(xht h)
iteration
void xhash_walk(xht h, xhash_walker w, void *arg)
int sx_websocket_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
jqueue_t jqueue_new(void)
void set_debug_flag(int v)
int sx_ssl_init(sx_env_t env, sx_plugin_t p, va_list args)
args: name, pemfile, cachain, mode
int websocket
websocket support
static void _c2s_ar_free(const char *module, int modulelen, void *val, void *arg)
int config_load(config_t c, const char *file)
turn an xml file into a config hash
int access_allow(access_t access, const char *ip, const char *mask)
const char * local_ciphers
list of TLS ciphers
int sx_compress_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
static sig_atomic_t c2s_shutdown
pool_t xhash_pool(xht h)
get our pool
const char * packet_stats
static sig_atomic_t c2s_logrotate
const char * ar_module_name
default auth/reg module
char * pstrdup(pool_t p, const char *src)
XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is wit...
int local_ssl_port
encrypted port
void * xhash_get(xht h, const char *key)
#define mio_close(m, fd)
request that mio close this fd
char * j_attr(const char **atts, const char *attr)
void authreg_free(authreg_t ar)
shutdown the authreg system
log_t log_new(log_type_t type, const char *ident, const char *facility)
const char * config_get_one(config_t c, const char *key, int num)
get config value n for this key
const char * ar_register_oob
#define sx_sasl_cb_GEN_AUTHZID
jqueue_t dead
list of sx_t on the way out
const char * pbx_pipe
PBX integration named pipe.
void sx_env_free(sx_env_t env)
int host_require_starttls
require starttls
authreg_t authreg_init(c2s_t c2s, const char *name)
get a handle for the named module
const char * local_private_key_password
private key password
sig_atomic_t c2s_lost_router
#define sx_sasl_cb_CHECK_PASS
static sig_atomic_t c2s_sighup
int c2s_router_mio_callback(mio_t m, mio_action_t a, mio_fd_t fd, void *data, void *arg)
int stanza_rate_total
stanza rates
const char * local_pemfile
encrypted port pemfile
const char * local_cachain
encrypted port cachain file
static void _c2s_hosts_expand(c2s_t c2s)
#define sx_sasl_cb_GET_PASS
const char * host_cachain
certificate chain
int byte_rate_total
byte rates (karma)