/** make a new one */ static user_t _user_alloc(sm_t sm, jid_t jid) { pool_t p; user_t user; p = pool_new(); user = (user_t) pmalloco(p, sizeof(struct user_st)); user->p = p; user->sm = sm; user->jid = jid_dup(jid); pool_cleanup(p, (void (*)(void *)) jid_free, user->jid); /* a place for modules to store stuff */ user->module_data = (void **) pmalloco(p, sizeof(void *) * sm->mm->nindex); return user; }
/** see if a jid is in an acl */ int aci_check(xht acls, char *type, jid_t jid) { jid_t list, dup; dup = jid_dup(jid); if (dup->resource[0]) { /* resourceless version */ dup->resource[0] = '\0'; dup->dirty = 1; } log_debug(ZONE, "checking for '%s' in acl 'all'", jid_full(jid)); list = (jid_t) xhash_get(acls, "all"); if(jid_search(list, jid)) { jid_free(dup); return 1; } log_debug(ZONE, "checking for '%s' in acl 'all'", jid_user(dup)); if(jid_search(list, dup)) { jid_free(dup); return 1; } if(type != NULL) { log_debug(ZONE, "checking for '%s' in acl '%s'", jid_full(jid), type); list = (jid_t) xhash_get(acls, type); if(jid_search(list, jid)) { jid_free(dup); return 1; } log_debug(ZONE, "checking for '%s' in acl '%s'", jid_user(dup), type); if(jid_search(list, dup)) { jid_free(dup); return 1; } } jid_free(dup); return 0; }
/** presence from the session */ static mod_ret_t _presence_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) { /* only handle presence */ if(!(pkt->type & pkt_PRESENCE)) return mod_PASS; /* reset from if necessary */ if(pkt->from == NULL || jid_compare_user(pkt->from, sess->jid) != 0) { if(pkt->from != NULL) jid_free(pkt->from); pkt->from = jid_dup(sess->jid); nad_set_attr(pkt->nad, 1, -1, "from", jid_full(pkt->from), 0); } /* presence broadcast (T1, T2, T3) */ if(pkt->to == NULL) pres_update(sess, pkt); /* directed presence (T7, T8) */ else pres_deliver(sess, pkt); return mod_HANDLED; }
sess_t sess_start(sm_t sm, jid_t jid) { pool_t p; user_t user; sess_t sess, scan; sha1_state_t sha1; unsigned char hash[20]; int replaced = 0; log_debug(ZONE, "session requested for %s", jid_full(jid)); /* check whether it is to serviced domain */ if(xhash_get(sm->hosts, jid->domain) == NULL) { log_write(sm->log, LOG_ERR, "request to start session in non-serviced domain: jid=%s", jid_full(jid)); return NULL; } /* get user data for this guy */ user = user_load(sm, jid); /* unknown user */ if(user == NULL) { if(config_get(sm->config, "user.auto-create") == NULL) { log_write(sm->log, LOG_NOTICE, "user not found and user.auto-create not enabled, can't start session: jid=%s", jid_full(jid)); return NULL; } log_debug(ZONE, "auto-creating user %s", jid_user(jid)); if(user_create(sm, jid) != 0) return NULL; user = user_load(sm, jid); if(user == NULL) { log_write(sm->log, LOG_NOTICE, "couldn't load user, can't start session: jid=%s", jid_full(jid)); return NULL; } } /* kill their old session if they have one */ for(scan = user->sessions; scan != NULL; scan = scan->next) if(jid_compare_full(scan->jid, jid) == 0) { log_debug(ZONE, "replacing session %s (%s)", jid_full(jid), scan->c2s_id); /* !!! this "replaced" stuff is a hack - its really a subaction of "ended". * hurrah, another control protocol rewrite is needed :( */ sm_c2s_action(scan, "replaced", NULL); _sess_end_guts(scan); pool_free(scan->p); replaced = 1; break; } /* make a new session */ p = pool_new(); sess = (sess_t) pmalloco(p, sizeof(struct sess_st)); sess->p = p; /* fill it out */ sess->pri = 0; sess->user = user; sess->jid = jid_dup(jid); pool_cleanup(sess->p, (void (*))(void *) jid_free, sess->jid); /* a place for modules to store stuff */ sess->module_data = (void **) pmalloco(sess->p, sizeof(void *) * sess->user->sm->mm->nindex); /* add it to the list */ sess->next = user->sessions; user->sessions = sess; /* who c2s should address things to */ sha1_init(&sha1); datetime_out(time(NULL), dt_DATETIME, sess->sm_id, 41); sha1_append(&sha1, sess->sm_id, strlen(sess->sm_id)); sha1_append(&sha1, jid_full(sess->jid), strlen(jid_full(sess->jid))); sha1_finish(&sha1, hash); hex_from_raw(hash, 20, sess->sm_id); log_debug(ZONE, "smid is %s", sess->sm_id); /* remember it */ xhash_put(sm->sessions, sess->sm_id, sess); /* inform the modules */ /* !!! catch the return value - if its 1, don't let them in */ mm_sess_start(sm->mm, sess); if(replaced) log_write(sm->log, LOG_NOTICE, "session replaced: jid=%s", jid_full(sess->jid)); else log_write(sm->log, LOG_NOTICE, "session started: jid=%s", jid_full(sess->jid)); return sess; }