예제 #1
0
파일: user.c 프로젝트: 6wei/jabberd2
/** fetch user data */
user_t user_load(sm_t sm, jid_t jid) {
    user_t user;

    /* already loaded */
    user = xhash_get(sm->users, jid_user(jid));
    if(user != NULL) {
        log_debug(ZONE, "returning previously-created user data for %s", jid_user(jid));
        return user;
    }

    /* make a new one */
    user = _user_alloc(sm, jid);

    /* get modules to setup */
    if(mm_user_load(sm->mm, user) != 0) {
        log_debug(ZONE, "modules failed user load for %s", jid_user(jid));
        pool_free(user->p);
        return NULL;
    }

    /* save them for later */
    xhash_put(sm->users, jid_user(user->jid), (void *) user);

    log_debug(ZONE, "loaded user data for %s", jid_user(jid));

    return user;
}
예제 #2
0
파일: user.c 프로젝트: 6wei/jabberd2
/** trash a user */
void user_delete(sm_t sm, jid_t jid) {
    user_t user;
    sess_t scan, next;

    log_debug(ZONE, "delete user request for %s", jid_user(jid));

    user = user_load(sm, jid);
    if(user == NULL) {
        log_debug(ZONE, "user doesn't exist, can't delete");
        return;
    }

    /* close their sessions first (this will free user, after the last session ends) */
    scan = user->sessions;
    while(scan != NULL) {
        next = scan->next;
        sm_c2s_action(scan, "ended", NULL);
        sess_end(scan);
        scan = next;
    }

    mm_user_delete(sm->mm, jid);

    log_write(sm->log, LOG_NOTICE, "deleted user: jid=%s", jid_user(jid));
}
예제 #3
0
파일: user.c 프로젝트: 6wei/jabberd2
/** initialise a user */
int user_create(sm_t sm, jid_t jid) {
    user_t user;

    log_debug(ZONE, "create user request for %s", jid_user(jid));

    /* check whether it is to serviced domain */
    if(xhash_get(sm->hosts, jid->domain) == NULL) {
        log_write(sm->log, LOG_ERR, "request to create user for non-serviced domain: jid=%s", jid_user(jid));
        log_debug(ZONE, "no such domain, not creating");
        return 1;
    }

    user = user_load(sm, jid);
    if(user != NULL) {
        log_write(sm->log, LOG_ERR, "request to create already-active user: jid=%s", jid_user(jid));
        log_debug(ZONE, "user already active, not creating");
        return 1;
    }

    /* modules create */
    if(mm_user_create(sm->mm, jid) != 0) {
        log_write(sm->log, LOG_ERR, "user creation failed: jid=%s", jid_user(jid));
        log_debug(ZONE, "user create failed, forcing deletion for cleanup");
        mm_user_delete(sm->mm, jid);
        return 1;
    }

    log_write(sm->log, LOG_NOTICE, "created user: jid=%s", jid_user(jid));

    return 0;
}
예제 #4
0
/* drop incoming presence if the user isn't around,
 * so we don't have to load them during broadcasts */
mod_ret_t _presence_in_router(mod_instance_t mi, pkt_t pkt) {
    user_t user;
    sess_t sess;

    /* only check presence to users, pass presence to sm and probes */
    if(!(pkt->type & pkt_PRESENCE) || pkt->to->node[0] == '\0' || pkt->type == pkt_PRESENCE_PROBE)
        return mod_PASS;

    /* get the user _without_ doing a load */
    user = xhash_get(mi->mod->mm->sm->users, jid_user(pkt->to));

    /* no user, or no sessions, bail */
    if(user == NULL || user->sessions == NULL) {
        pkt_free(pkt);
        return mod_HANDLED;
    }

    /* only pass if there's at least one available session */
    for(sess = user->sessions; sess != NULL; sess = sess->next)
        if(sess->available)
            return mod_PASS;

    /* no available sessions, drop */
    pkt_free(pkt);

    return mod_HANDLED;
}
예제 #5
0
파일: mod_vacation.c 프로젝트: zipo/zipo
static int _vacation_user_load(mod_instance_t mi, user_t user) {
    module_t mod = mi->mod;
    vacation_t v;
    os_t os;
    os_object_t o;

    v = (vacation_t) calloc(1, sizeof(struct _vacation_st));
    user->module_data[mod->index] = v;

    if(storage_get(mod->mm->sm->st, "vacation-settings", jid_user(user->jid), NULL, &os) == st_SUCCESS) {
        if(os_iter_first(os)) {
            o = os_iter_object(os);

            if(os_object_get_time(os, o, "start", &v->start) &&
               os_object_get_time(os, o, "end", &v->end) &&
               os_object_get_str(os, o, "message", &v->msg))
                v->msg = strdup(v->msg);
            else {
                v->start = 0;
                v->end = 0;
                v->msg = NULL;
            }
        }

        os_free(os);
    }

    pool_cleanup(user->p, (void (*))(void *) _vacation_user_free, v);

    return 0;
}
예제 #6
0
static void _roster_publish_save_item(user_t user, item_t item) {
    os_t os;
    os_object_t o;
    char filter[4096];
    int i;

    log_debug(ZONE, "saving roster item %s for %s", jid_full(item->jid), jid_user(user->jid));

    os = os_new();
    o = os_object_new(os);

    os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);

    if(item->name != NULL)
        os_object_put(o, "name", item->name, os_type_STRING);

    os_object_put(o, "to", &item->to, os_type_BOOLEAN);
    os_object_put(o, "from", &item->from, os_type_BOOLEAN);
    os_object_put(o, "ask", &item->ask, os_type_INTEGER);

    snprintf(filter, 4096, "(jid=%s)", jid_full(item->jid));

    storage_replace(user->sm->st, "roster-items", jid_user(user->jid), filter, os);

    os_free(os);

    snprintf(filter, 4096, "(jid=%s)", jid_full(item->jid));

    if(item->ngroups == 0) {
        storage_delete(user->sm->st, "roster-groups", jid_user(user->jid), filter);
        return;
    }

    os = os_new();

    for(i = 0; i < item->ngroups; i++) {
        o = os_object_new(os);

        os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);
        os_object_put(o, "group", item->groups[i], os_type_STRING);
    }

    storage_replace(user->sm->st, "roster-groups", jid_user(user->jid), filter, os);

    os_free(os);
}
예제 #7
0
static int _active_user_create(mod_instance_t mi, jid_t jid) {
    time_t t;
    os_t os;
    os_object_t o;

    log_debug(ZONE, "activating user %s", jid_user(jid));

    t = time(NULL);

    os = os_new();
    o = os_object_new(os);
    os_object_put_time(o, "time", &t);
    storage_put(mi->sm->st, "active", jid_user(jid), os);
    os_free(os);

    return 0;
}
예제 #8
0
/* presence packets to the sm */
static mod_ret_t _presence_pkt_sm(mod_instance_t mi, pkt_t pkt) {
    module_t mod = mi->mod;
    jid_t smjid;

    /* only check presence/subs to server JID */
    if(!(pkt->type & pkt_PRESENCE || pkt->type & pkt_S10N))
        return mod_PASS;

    smjid = jid_new(jid_user(pkt->to), -1);

    /* handle subscription requests */
    if(pkt->type == pkt_S10N) {
        log_debug(ZONE, "accepting subscription request from %s", jid_full(pkt->from));

        /* accept request */
        pkt_router(pkt_create(mod->mm->sm, "presence", "subscribed", jid_user(pkt->from), jid_user(smjid)));

        /* and subscribe back to theirs */
        pkt_router(pkt_create(mod->mm->sm, "presence", "subscribe", jid_user(pkt->from), jid_user(smjid)));

        pkt_free(pkt);
        jid_free(smjid);
        return mod_HANDLED;
    }

    /* handle unsubscribe requests */
    if(pkt->type == pkt_S10N_UN) {
        log_debug(ZONE, "accepting unsubscribe request from %s", jid_full(pkt->from));

        /* ack the request */
        pkt_router(pkt_create(mod->mm->sm, "presence", "unsubscribed", jid_user(pkt->from), jid_user(smjid)));

        pkt_free(pkt);
        jid_free(smjid);
        return mod_HANDLED;
    }

    /* drop the rest */
    log_debug(ZONE, "dropping presence from %s", jid_full(pkt->from));
    pkt_free(pkt);
    jid_free(smjid);
    return mod_HANDLED;

}
예제 #9
0
mreturn mod_roster_auto_in_s10n(mapi m, void *arg)
{
	xmlnode reply, x;

	log_debug("AUTO ROSTER");

	//in not s10n
	if (m->packet->type != JPACKET_S10N)
		return M_IGNORE;
	//if no to
	if (m->packet->to == NULL)
		return M_PASS;
	//if from me
	if (jid_cmpx(m->s->uid, m->packet->from, JID_USER | JID_SERVER) ==
	    0)
		return M_PASS;

	log_debug("handling incoming s10n");

	switch (jpacket_subtype(m->packet)) {
	case JPACKET__SUBSCRIBE:
		log_debug("SUBSCRIBE");
		reply =
		    jutil_presnew(JPACKET__SUBSCRIBED,
				  jid_full(m->packet->from), NULL);
		js_session_from(m->s, jpacket_new(reply));
		reply =
		    jutil_presnew(JPACKET__SUBSCRIBE,
				  jid_full(m->packet->from), NULL);
		js_session_from(m->s, jpacket_new(reply));
		break;
	case JPACKET__SUBSCRIBED:
		break;
	case JPACKET__UNSUBSCRIBE:
		log_debug("UNSUBSCRIBE");
		//reply = jutil_presnew(JPACKET__UNSUBSCRIBED, jid_full(m->packet->from),NULL);
		//js_session_from(m->s, jpacket_new(reply));
		//remove account.
		reply = jutil_iqnew(JPACKET__SET, NS_ROSTER);
		x = xmlnode_get_tag(reply, "query");
		x = xmlnode_insert_tag(x, "item");
		xmlnode_put_attrib(x, "jid",
				   jid_full(jid_user(m->packet->from)));
		xmlnode_put_attrib(x, "subscription", "remove");
		js_session_from(m->s, jpacket_new(reply));

		// reply = jutil_iqnewpresnew(JPACKET__UNSUBSCRIBE, jid_full(m->packet->from),NULL);
		// js_session_from(m->s, jpacket_new(reply));
		break;
	case JPACKET__UNSUBSCRIBED:
		break;
	}

	xmlnode_free(m->packet->x);
	return M_HANDLED;
}
예제 #10
0
파일: aci.c 프로젝트: caoxiaokang/jabberd2
/** 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;
}
예제 #11
0
파일: aci.c 프로젝트: caoxiaokang/jabberd2
xht aci_load(sm_t sm)
{
    xht acls;
    int aelem, jelem, attr;
    char type[33];
    jid_t list, jid;

    log_debug(ZONE, "loading aci");

    acls = xhash_new(51);

    if((aelem = nad_find_elem(sm->config->nad, 0, -1, "aci", 1)) < 0)
        return acls;

    aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 1);
    while(aelem >= 0)
    {
        list = NULL;

        if((attr = nad_find_attr(sm->config->nad, aelem, -1, "type", NULL)) < 0)
        {
            aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 0);
            continue;
        }

        snprintf(type, 33, "%.*s", NAD_AVAL_L(sm->config->nad, attr), NAD_AVAL(sm->config->nad, attr));

        log_debug(ZONE, "building list for '%s'", type);

        jelem = nad_find_elem(sm->config->nad, aelem, -1, "jid", 1);
        while(jelem >= 0)
        {
            if(NAD_CDATA_L(sm->config->nad, jelem) > 0)
            {
                jid = jid_new(NAD_CDATA(sm->config->nad, jelem), NAD_CDATA_L(sm->config->nad, jelem));
                list = jid_append(list, jid);
                
                log_debug(ZONE, "added '%s'", jid_user(jid));

                jid_free(jid);
            }

            jelem = nad_find_elem(sm->config->nad, jelem, -1, "jid", 0);
        }

        if(list != NULL) {
            xhash_put(acls, pstrdup(xhash_pool(acls), type), (void *) list);
        }

        aelem = nad_find_elem(sm->config->nad, aelem, -1, "acl", 0);
    }

    return acls;
}
예제 #12
0
파일: mod_roster.c 프로젝트: zipo/zipo
/** free the roster */
static void _roster_free(user_t user)
{
    if(user->roster == NULL)
        return;

    log_debug(ZONE, "freeing roster for %s", jid_user(user->jid));

    xhash_walk(user->roster, _roster_free_walker, NULL);

    xhash_free(user->roster);
    user->roster = NULL;
}
예제 #13
0
static int _active_user_load(mod_instance_t mi, user_t user) {
    os_t os;
    os_object_t o;

    /* get their active status */
    if(storage_get(user->sm->st, "active", jid_user(user->jid), NULL, &os) == st_SUCCESS && os_iter_first(os)) {
        o = os_iter_object(os);
        os_object_get_time(os, o, "time", &user->active);
        os_free(os);
    } else
        /* can't load them if they're inactive */
        return 1;

    return 0;
}
예제 #14
0
파일: sess.c 프로젝트: 6wei/jabberd2
void sess_end(sess_t sess) {
    log_debug(ZONE, "shutting down session %s", jid_full(sess->jid));

    _sess_end_guts(sess);

    log_write(sess->user->sm->log, LOG_NOTICE, "session ended: jid=%s", jid_full(sess->jid));

    /* if it was the last session, free the user */
    if(sess->user->sessions == NULL) {
        mm_user_unload(sess->user->sm->mm, sess->user);
        log_write(sess->user->sm->log, LOG_NOTICE, "user unloaded jid=%s", jid_user(sess->jid));
        user_free(sess->user);
    }

    /* free the session */
    pool_free(sess->p);
}
예제 #15
0
mreturn mod_browse_server(mapi m, void *arg)
{
	xmlnode browse, query, x;

	if (m->packet->type != JPACKET_IQ)
		return M_IGNORE;
	if (jpacket_subtype(m->packet) != JPACKET__GET
	    || !NSCHECK(m->packet->iq, NS_BROWSE)
	    || m->packet->to->resource != NULL)
		return M_PASS;

	/* get data from the config file */
	if ((browse = js_config(m->si, "browse")) == NULL)
		return M_PASS;

	log_debug("handling browse query");

	/* build the result IQ */
	query =
	    xmlnode_insert_tag(jutil_iqresult(m->packet->x), "service");
	xmlnode_put_attrib(query, "xmlns", NS_BROWSE);
	xmlnode_put_attrib(query, "type", "jabber");
	xmlnode_put_attrib(query, "jid", m->packet->to->server);
	xmlnode_put_attrib(query, "name", xmlnode_get_data(js_config(m->si, "vCard/FN")));	/* pull name from the server vCard */

	/* copy in the configured services */
	xmlnode_insert_node(query, xmlnode_get_firstchild(browse));

	/* list the admin stuff */
	if (js_admin_jid(m->si, jid_user(m->packet->from), ADMIN_READ)) {
		x = xmlnode_insert_tag(query, "item");
		xmlnode_put_attrib(x, "jid",
				   spools(xmlnode_pool(x),
					  m->packet->to->server, "/admin",
					  xmlnode_pool(x)));
		xmlnode_put_attrib(x, "name", "Online Users");
		xmlnode_insert_cdata(xmlnode_insert_tag(query, "ns"),
				     NS_ADMIN, -1);
	}

	jpacket_reset(m->packet);
	js_deliver(m->si, m->packet);

	return M_HANDLED;
}
예제 #16
0
파일: conference_room.c 프로젝트: bcy/muc
/* returns a valid nick from the list, x is the first <nick>foo</nick> xmlnode, checks siblings */
char *con_room_nick(cnr room, cnu user, xmlnode x)
{
  char *nick = NULL;
  xmlnode cur;
  int count = 1;

  if(room == NULL || user == NULL) 
  {
    log_warn(NAME, "[%s] Aborting - NULL attribute found", FZONE);
    return NULL;
  }

  log_debug(NAME, "[%s] looking for valid nick in room %s from starter %s", FZONE, jid_full(room->id), xmlnode2str(x));

  /* make-up-a-nick phase */
  if(x == NULL)
  {
    nick = pmalloco(user->p, j_strlen(user->realid->user) + 10);
    log_debug(NAME, "[%s] Malloc: Nick = %d", FZONE, j_strlen(user->realid->user) + 10);

    sprintf(nick, "%s", user->realid->user);
    while(g_hash_table_lookup(room->local, nick) != NULL)
      sprintf(nick, "%s%d", user->realid->user,count++);
    return nick;
  }

  /* scan the list */
  for(cur = x; cur != NULL; cur = xmlnode_get_nextsibling(cur))
  {
    if(j_strcmp(xmlnode_get_name(cur),"nick") == 0 && (nick = xmlnode_get_data(cur)) != NULL)
      if(g_hash_table_lookup(room->local, nick) == NULL)
        break;
  }

  if(is_registered(room->master, jid_full(jid_user(user->realid)), nick) == -1)
    nick = NULL;

  return nick;
}
예제 #17
0
static void _iq_private_user_delete(mod_instance_t mi, jid_t jid) {
    log_debug(ZONE, "deleting private xml storage for %s", jid_user(jid));

    storage_delete(mi->sm->st, "private", jid_user(jid), NULL);
}
예제 #18
0
static mod_ret_t _offline_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    st_ret_t ret;
    os_t os;
    os_object_t o;
    nad_t nad;
    pkt_t queued;
    int ns, elem, attr;
    char cttl[15], cstamp[18];
    time_t ttl, stamp;

    /* if they're becoming available for the first time */
    if(pkt->type == pkt_PRESENCE && pkt->to == NULL && sess->user->top == NULL) {

        ret = storage_get(pkt->sm->st, "queue", jid_user(sess->jid), NULL, &os);
        if(ret != st_SUCCESS) {
            log_debug(ZONE, "storage_get returned %d", ret);
            return mod_PASS;
        }

        if(os_iter_first(os))
            do {
                o = os_iter_object(os);

                if(os_object_get_nad(os, o, "xml", &nad)) {
                    queued = pkt_new(pkt->sm, nad_copy(nad));
                    if(queued == NULL) {
                        log_debug(ZONE, "invalid queued packet, not delivering");
                    } else {
                        /* check expiry as necessary */
                        if((ns = nad_find_scoped_namespace(queued->nad, uri_EXPIRE, NULL)) >= 0 &&
                                (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
                                (attr = nad_find_attr(queued->nad, elem, -1, "seconds", NULL)) >= 0) {
                            snprintf(cttl, 15, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
                            ttl = atoi(cttl);

                            /* it should have a x:delay stamp, because we stamp everything we store */
                            if((ns = nad_find_scoped_namespace(queued->nad, uri_DELAY, NULL)) >= 0 &&
                                    (elem = nad_find_elem(queued->nad, 1, ns, "x", 1)) >= 0 &&
                                    (attr = nad_find_attr(queued->nad, elem, -1, "stamp", NULL)) >= 0) {
                                snprintf(cstamp, 18, "%.*s", NAD_AVAL_L(queued->nad, attr), NAD_AVAL(queued->nad, attr));
                                stamp = datetime_in(cstamp);

                                if(stamp + ttl <= time(NULL)) {
                                    log_debug(ZONE, "queued packet has expired, dropping");
                                    pkt_free(queued);
                                    continue;
                                }
                            }
                        }

                        log_debug(ZONE, "delivering queued packet to %s", jid_full(sess->jid));
                        pkt_sess(queued, sess);
                    }
                }
            } while(os_iter_next(os));

        os_free(os);

        /* drop the spool */
        storage_delete(pkt->sm->st, "queue", jid_user(sess->jid), NULL);
    }

    /* pass it so that other modules and mod_presence can get it */
    return mod_PASS;
}
예제 #19
0
파일: user.c 프로젝트: 6wei/jabberd2
void user_free(user_t user) {
    log_debug(ZONE, "freeing user %s", jid_user(user->jid));

    xhash_zap(user->sm->users, jid_user(user->jid));
    pool_free(user->p);
}
예제 #20
0
/** register set handler */
static void _authreg_register_set(c2s_t c2s, sess_t sess, nad_t nad)
{
    int ns = 0, elem, attr;
    char username[1024], password[1024];

    /* if we're not configured for registration (or pw changes), or we can't set passwords, fail outright */
    if(!(sess->host->ar_register_enable || sess->host->ar_register_password) || c2s->ar->set_password == NULL) {
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
        return;
    }

    ns = nad_find_scoped_namespace(nad, uri_REGISTER, NULL);

    /* removals */
    if(sess->active && nad_find_elem(nad, 1, ns, "remove", 1) >= 0) {
        /* only if full reg is enabled */
        if(!sess->host->ar_register_enable) {
            sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
            return;
        }

        log_debug(ZONE, "user remove requested");

        /* make sure we can delete them */
        if(c2s->ar->delete_user == NULL) {
            sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
            return;
        }

        /* otherwise, delete them */
        if((c2s->ar->delete_user)(c2s->ar, sess->resources->jid->node, sess->host->realm) != 0) {
            log_debug(ZONE, "user delete failed");
            sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
            return;
        }

        log_write(c2s->log, LOG_NOTICE, "[%d] deleted user: user=%s; realm=%s", sess->s->tag, sess->resources->jid->node, sess->host->realm);

        log_write(c2s->log, LOG_NOTICE, "[%d] registration remove succeeded, requesting user deletion: jid=%s", sess->s->tag, jid_user(sess->resources->jid));

        /* make a result nad */
        sess->result = nad_new();

        ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);

        nad_append_elem(sess->result, ns, "iq", 0);
        nad_set_attr(sess->result, 0, -1, "type", "result", 6);

        /* extract the id */
        attr = nad_find_attr(nad, 0, -1, "id", NULL);
        if(attr >= 0)
            nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));

        nad_free(nad);

        sx_nad_write(sess->s, sess->result);
        sess->result = NULL;

        /* get the sm to delete them (it will force their sessions to end) */
        sm_delete(sess, sess->resources);

        return;
    }

    /* username is required */
    elem = nad_find_elem(nad, 1, ns, "username", 1);
    if(elem < 0)
    {
        log_debug(ZONE, "register set with no username, bouncing it");
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
        return;
    }

    snprintf(username, 1024, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));
    if(stringprep_xmpp_nodeprep(username, 1024) != 0) {
        log_debug(ZONE, "register set username failed nodeprep, bouncing it");
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_JID_MALFORMED), 0));
        return;
    }

    elem = nad_find_elem(nad, 1, ns, "password", 1);
    if(elem < 0)
    {
        log_debug(ZONE, "register set with no password, bouncing it");
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_BAD_REQUEST), 0));
        return;
    }

    /* if they're already auth'd, its a password change */
    if(sess->active)
    {
        /* confirm that the username matches their auth id */
        if(strcmp(username, sess->resources->jid->node) != 0)
        {
            log_debug(ZONE, "%s is trying to change password for %s, bouncing it", jid_full(sess->resources->jid), username);
            sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_OLD_UNAUTH), 0));
            return;
        }
    }

    /* can't go on if we're not doing full reg */
    else if(!sess->host->ar_register_enable) {
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
        return;
    }

    /* if they exist, bounce */
    else if((c2s->ar->user_exists)(c2s->ar, username, sess->host->realm))
    {
        log_debug(ZONE, "attempt to register %s, but they already exist", username);
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_CONFLICT), 0));
        return;
    }

    /* make sure we can create them */
    else if(c2s->ar->create_user == NULL)
    {
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_NOT_ALLOWED), 0));
        return;
    }

    /* otherwise, create them */
    else if((c2s->ar->create_user)(c2s->ar, username, sess->host->realm) != 0)
    {
        log_debug(ZONE, "user create failed");
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
        return;
    }

    else
        log_write(c2s->log, LOG_NOTICE, "[%d] created user: user=%s; realm=%s", sess->s->tag, username, sess->host->realm);

    /* extract the password */
    snprintf(password, 257, "%.*s", NAD_CDATA_L(nad, elem), NAD_CDATA(nad, elem));

    /* change it */
    if((c2s->ar->set_password)(c2s->ar, username, sess->host->realm, password) != 0)
    {
        log_debug(ZONE, "password store failed");
        sx_nad_write(sess->s, stanza_tofrom(stanza_error(nad, 0, stanza_err_INTERNAL_SERVER_ERROR), 0));
        return;
    }

    log_debug(ZONE, "updated auth creds for %s", username);

    /* make a result nad */
    sess->result = nad_new();

    ns = nad_add_namespace(sess->result, uri_CLIENT, NULL);

    nad_append_elem(sess->result, ns, "iq", 0);
    nad_set_attr(sess->result, 0, -1, "type", "result", 6);

    /* extract the id */
    attr = nad_find_attr(nad, 0, -1, "id", NULL);
    if(attr >= 0)
        nad_set_attr(sess->result, 0, -1, "id", NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr));

    /* if they're active, then this was just a password change, and we're done */
    if(sess->active) {
        log_write(c2s->log, LOG_NOTICE, "[%d] password changed: jid=%s", sess->s->tag, jid_user(sess->resources->jid));
        sx_nad_write(sess->s, sess->result);
        sess->result = NULL;
        return;
    }

    /* create new bound jid holder */
    if(sess->resources == NULL) {
        sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
    }

    /* our local id */
    sprintf(sess->resources->c2s_id, "%d", sess->s->tag);

    /* the user jid for this transaction */
    sess->resources->jid = jid_new(sess->s->req_to, -1);
    jid_reset_components(sess->resources->jid, username, sess->resources->jid->domain, sess->resources->jid->resource);

    log_write(c2s->log, LOG_NOTICE, "[%d] registration succeeded, requesting user creation: jid=%s", sess->s->tag, jid_user(sess->resources->jid));

    /* get the sm to create them */
    sm_create(sess, sess->resources);

    nad_free(nad);

    return;
}
예제 #21
0
/**
 * process commandline
 * @return: 0 to indicate that output needs to be written
 */
int _pbx_process_command(c2s_t c2s, char *cmd)
{
	jid_t jid;
	int action = 0, len;
	sess_t sess;
	unsigned char hashbuf[44] = "PBX";
	unsigned char *sesshash;

	sesshash = hashbuf+3;

	/* get command */
	if(!strncasecmp("START ", cmd, 6)) {
		cmd += 6;
		action = 1;
	}
	if(!strncasecmp("STOP ", cmd, 5)) {
		cmd += 5;
		action = 2;
	}
	if(action != 0) {
		len = _pbx_command_part_len(cmd);
		if(len > 0) {
			jid = jid_new(cmd, len);
			if(jid) {
				cmd += len;
				if(*cmd != '\0') cmd++;

				shahash_r(jid_full(jid), sesshash);
				sess = xhash_get(c2s->sessions, hashbuf);

				switch(action) {
					case 1:
						log_debug(ZONE, "STARTing session for %s/%s (%s) with commandline: %s", jid_user(jid), jid->resource, hashbuf, cmd);

						if(sess == NULL) {
						/* create new session */
							sess = (sess_t) calloc(1, sizeof(struct sess_st));
							sess->c2s = c2s;
							sess->last_activity = time(NULL);
							/* put into sessions hash */
							snprintf(sess->skey, sizeof(sess->skey), "%s", hashbuf);
							xhash_put(c2s->sessions, sess->skey, (void *) sess);
							/* generate bound resource */
							sess->resources = (bres_t) calloc(1, sizeof(struct bres_st));
							snprintf(sess->resources->c2s_id, sizeof(sess->resources->c2s_id), "%s", hashbuf);
							sess->resources->jid = jid;
							/* open SM session */
							log_write(sess->c2s->log, LOG_NOTICE, "[PBX] requesting session: jid=%s", jid_full(jid));
							sm_start(sess, sess->resources);

							/* generate presence packet to get session online */
							/* a bit hacky, but we need to emulate _some_ of the client behavior */
							sess->result = _pbx_presence_nad(1, cmd);
						}
						else {
							/* just send the presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(1, cmd));
						}

						break;

					case 2:
						log_debug(ZONE, "STOPping session for %s/%s with commandline: %s", jid_user(jid), jid->resource, cmd);

						if(sess != NULL) {
							/* send unavailable presence */
							sm_packet(sess, sess->resources, _pbx_presence_nad(0, cmd));
							/* end the session */
							sm_end(sess, sess->resources);
							xhash_zap(c2s->sessions, sess->skey);
							jqueue_push(c2s->dead_sess, (void *) sess, 0);
						}

						break;
				}

				/* TODO: respond with "OK", return 0 */
				return -1;
			}
		}
		/* TODO: generate "ERR" response, return 0 */
		return -1;
	}
	if(!strncasecmp("STATUS", cmd, 6)) {
		log_write(c2s->log, LOG_INFO, "STATUS PBX command not implemented yet");
		return -1;
	}
    return -1;
}
예제 #22
0
파일: router.c 프로젝트: 6wei/jabberd2
static void _router_process_route(component_t comp, nad_t nad) {
    int atype, ato, afrom;
    unsigned int dest;
    struct jid_st sto, sfrom;
    jid_static_buf sto_buf, sfrom_buf;
    jid_t to = NULL, from = NULL;
    routes_t targets;
    component_t target;
    union xhashv xhv;

    /* init static jid */
    jid_static(&sto,&sto_buf);
    jid_static(&sfrom,&sfrom_buf);

    if(nad_find_attr(nad, 0, -1, "error", NULL) >= 0) {
        log_debug(ZONE, "dropping error packet, trying to avoid loops");
        nad_free(nad);
        return;
    }

    atype = nad_find_attr(nad, 0, -1, "type", NULL);
    ato = nad_find_attr(nad, 0, -1, "to", NULL);
    afrom = nad_find_attr(nad, 0, -1, "from", NULL);

    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
    if(afrom >= 0) from = jid_reset(&sfrom, NAD_AVAL(nad, afrom), NAD_AVAL_L(nad, afrom));

    /* unicast */
    if(atype < 0) {
        if(to == NULL || from == NULL) {
            log_debug(ZONE, "unicast route with missing or invalid to or from, bouncing");
            nad_set_attr(nad, 0, -1, "error", "400", 3);
            _router_comp_write(comp, nad);
            return;
        }
        
        log_debug(ZONE, "unicast route from %s to %s", from->domain, to->domain);

        /* check the from */
        if(xhash_get(comp->routes, from->domain) == NULL) {
            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);
            nad_set_attr(nad, 0, -1, "error", "401", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* filter it */
        if(comp->r->filter != NULL) {
            int ret = filter_packet(comp->r, nad);
            if(ret == stanza_err_REDIRECT) {
                ato = nad_find_attr(nad, 0, -1, "to", NULL);
                if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
            }
            else if(ret > 0) {
                log_debug(ZONE, "packet filtered out: %s (%s)", _stanza_errors[ret - stanza_err_BAD_REQUEST].name, _stanza_errors[ret - stanza_err_BAD_REQUEST].code);
                nad_set_attr(nad, 0, -1, "error", _stanza_errors[ret - stanza_err_BAD_REQUEST].code, 3);
                _router_comp_write(comp, nad);
                return;
            }
        }

        /* find a target */
        targets = xhash_get(comp->r->routes, to->domain);
        if(targets == NULL) {
            if(comp->r->default_route != NULL && strcmp(from->domain, comp->r->default_route) == 0) {
                log_debug(ZONE, "%s is unbound, bouncing", from->domain);
                nad_set_attr(nad, 0, -1, "error", "404", 3);
                _router_comp_write(comp, nad);
                return;
            }
            targets = xhash_get(comp->r->routes, comp->r->default_route);
        }

        if(targets == NULL) {
            log_debug(ZONE, "%s is unbound, and no default route, bouncing", to->domain);
            nad_set_attr(nad, 0, -1, "error", "404", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* copy to any log sinks */
        if(xhash_count(comp->r->log_sinks) > 0)
            xhash_walk(comp->r->log_sinks, _router_route_log_sink, (void *) nad);

        /* get route candidate */
        if(targets->ncomp == 1) {
            dest = 0;
        }
        else {
            switch(targets->rtype) {
                case route_MULTI_TO:
                    ato = nad_find_attr(nad, 1, -1, "to", NULL);
                    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                    else {
                        ato = nad_find_attr(nad, 1, -1, "target", NULL);
                        if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                        else {
                            const char *out; int len;
                            nad_print(nad, 0, &out, &len);
                            log_write(comp->r->log, LOG_ERR, "Cannot get destination for multiple route: %.*s", len, out);
                        }
                    }
                    break;
                case route_MULTI_FROM:
                    ato = nad_find_attr(nad, 1, -1, "from", NULL);
                    if(ato >= 0) to = jid_reset(&sto, NAD_AVAL(nad, ato), NAD_AVAL_L(nad, ato));
                    else {
                        const char *out; int len;
                        nad_print(nad, 0, &out, &len);
                        log_write(comp->r->log, LOG_ERR, "Cannot get source for multiple route: %.*s", len, out);
                    }
                    break;
                default:
                    log_write(comp->r->log, LOG_ERR, "Multiple components bound to single component route '%s'", targets->name);
                    /* simulate no 'to' info in this case */
            }
            if(to->node == NULL || strlen(to->node) == 0) {
                /* no node in destination JID - going random */
                dest = rand();
                log_debug(ZONE, "randomized to %u %% %d = %d", dest, targets->ncomp, dest % targets->ncomp);
            }
            else {
                /* use JID hash */
                unsigned char hashval[20];
                unsigned int *val;
                int i;
                
                shahash_raw(jid_user(to), hashval);
                
                val = (unsigned int *) hashval;
                dest = *val;
                for(i=1; i < 20 / (sizeof(unsigned int)/sizeof(unsigned char)); i++, val++) {
                    dest ^= *val;
                }
                dest >>= 2;

                log_debug(ZONE, "JID %s hashed to %u %% %d = %d", jid_user(to), dest, targets->ncomp, dest % targets->ncomp);

                /* jid_user() calls jid_expand() which may allocate some memory in _user and _full */
                if (to->_user != NULL )
                    free(to->_user);
                if (to->_full != NULL )
                    free(to->_full);
            }
            dest = dest % targets->ncomp;
        }

        target = targets->comp[dest];

        /* push it out */
        log_debug(ZONE, "writing route for '%s'*%u to %s, port %d", to->domain, dest+1, target->ip, target->port);

        /* if logging enabled, log messages that match our criteria */
        if (comp->r->message_logging_enabled && comp->r->message_logging_file != NULL) {
            int attr_msg_to;
            int attr_msg_from;
            int attr_route_to;
            int attr_route_from;
            jid_t jid_msg_from = NULL;
            jid_t jid_msg_to = NULL;
            jid_t jid_route_from = NULL;
            jid_t jid_route_to = NULL;

            if ((NAD_ENAME_L(nad, 1) == 7 && strncmp("message", NAD_ENAME(nad, 1), 7) == 0) &&		// has a "message" element 
                ((attr_route_from = nad_find_attr(nad, 0, -1, "from", NULL)) >= 0) &&
                ((attr_route_to = nad_find_attr(nad, 0, -1, "to", NULL)) >= 0) &&
                ((strncmp(NAD_AVAL(nad, attr_route_to), "c2s", 3)) != 0) &&							// ignore messages to "c2s" or we'd have dups
                ((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
                ((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
                ((attr_msg_from = nad_find_attr(nad, 1, -1, "from", NULL)) >= 0) &&
                ((attr_msg_to = nad_find_attr(nad, 1, -1, "to", NULL)) >= 0) &&
                ((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 
                ((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
            {
                message_log(nad, comp->r, jid_full(jid_msg_from), jid_full(jid_msg_to));
            }
            if (jid_msg_from != NULL)
                jid_free(jid_msg_from);
            if (jid_msg_to != NULL)
                jid_free(jid_msg_to);
            if (jid_route_from != NULL)
                jid_free(jid_route_from);
            if (jid_route_to != NULL)
                jid_free(jid_route_to);
        }

        _router_comp_write(target, nad);

        return;
    }

    /* broadcast */
    if(NAD_AVAL_L(nad, atype) == 9 && strncmp("broadcast", NAD_AVAL(nad, atype), 9) == 0) {
        if(from == NULL) {
            log_debug(ZONE, "broadcast route with missing or invalid from, bouncing");
            nad_set_attr(nad, 0, -1, "error", "400", 3);
            _router_comp_write(comp, nad);
            return;
        }
        
        log_debug(ZONE, "broadcast route from %s", from->domain);

        /* check the from */
        if(xhash_get(comp->routes, from->domain) == NULL) {
            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);
            nad_set_attr(nad, 0, -1, "error", "401", 3);
            _router_comp_write(comp, nad);
            return;
        }

        /* loop the components and distribute */
        if(xhash_iter_first(comp->r->components))
            do {
                xhv.comp_val = &target;
                xhash_iter_get(comp->r->components, NULL, NULL, xhv.val);

                if(target != comp) {
                    log_debug(ZONE, "writing broadcast to %s, port %d", target->ip, target->port);

                    _router_comp_write(target, nad_copy(nad));
                }
            } while(xhash_iter_next(comp->r->components));

        nad_free(nad);

        return;
    }

    log_debug(ZONE, "unknown route type '%.*s', dropping", NAD_AVAL_L(nad, atype), NAD_AVAL(nad, atype));

    nad_free(nad);
}
예제 #23
0
/** Callback processing incoming Jabber packets. */
result it_receive(instance i, dpacket d, void *arg) {
    iti ti = (iti) arg;
    jpacket jp;
    session s;
    session_ref alt_s;
    unsigned char *user;
    
    log_debug(ti->i->id,"Packet received: %s\n",xmlnode2str(d->x)); 

    switch(d->type) {
    case p_ROUTE: {
      /* ignore */
      return r_PASS;
    }
            
    case p_NONE:
    case p_NORM:
      jp = jpacket_new(d->x);
      break;

    default:
      return r_ERR;
    }

    if (!jp->from ||/* !jp->from->user ||*/ jp->type == JPACKET_UNKNOWN /* || jpacket_subtype(jp) == JPACKET__ERROR */)
    { /* ignore invalid packets */
        xmlnode_free(jp->x);
        return r_DONE;
    }

    /* JID user part should be case insensitive */
    /* convert user part of from JID to lower case */
    if(jp->from->user != NULL) 
	  for(user = jp->from->user; *user != '\0'; user++)
		if(*user < 128)
		  *user = tolower(*user);
	/* Mangle "from" JID, save original attribute for XDB conversion */
	xmlnode_put_attrib(jp->x, "origfrom", xmlnode_get_attrib(jp->x, "from"));
	xmlnode_put_attrib(jp->x, "from", jid_full(jp->from));

    SEM_LOCK(ti->sessions_sem);
    s = (session) wpxhash_get(ti->sessions,jid_full(jid_user(jp->from)));
    alt_s = (session_ref) wpxhash_get(ti->sessions_alt,jp->to->user);
    if (s != NULL) {
      if (s->exit_flag) {
    SEM_UNLOCK(ti->sessions_sem);
    log_alert("exit flag","message to exiting session");
    if (jp->type != JPACKET_PRESENCE){
      jutil_error(jp->x,TERROR_NOTFOUND);
      it_deliver(ti,jp->x);
    }
    else
      xmlnode_free(jp->x);
      } else if ((alt_s != NULL) && (
               (jp->type == JPACKET_MESSAGE)            // all messages
            || ((jp->type == JPACKET_IQ) && (j_strcmp(xmlnode_get_attrib(jp->iq,"xmlns"),NS_VCARD) == -1)) // all IQs except of vCard
            || (jp->type == JPACKET_PRESENCE) )) {      // all presences _targeted_to_specific_user_
        // rewriting "to" and "from" and putting packet back on the wire
        xmlnode_put_attrib(jp->x, "from", jid_full(it_uin2jid(jp->p,s->uin,jp->to->server)));
        xmlnode_put_attrib(jp->x, "to", jid_full(alt_s->s->orgid));
        SEM_UNLOCK(ti->sessions_sem);
        it_deliver(ti,jp->x);
      } else {
        jp->aux1 = (void *) s;
        mtq_send(s->q,jp->p,it_session_jpacket,(void *) jp);
        SEM_UNLOCK(ti->sessions_sem);
      }
    }
    else {
	  SEM_UNLOCK(ti->sessions_sem);

      if(jpacket_subtype(jp)!=JPACKET__ERROR)
    it_unknown(ti,jp);
      else
    xmlnode_free(jp->x);
    }
    return r_DONE;
}
예제 #24
0
파일: mod_amp.c 프로젝트: zipo/zipo
static mod_ret_t _amp_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    /* only handle messages */
    if (! pkt->type & pkt_MESSAGE)
        return mod_PASS;

    /* we're only interested in no to, to our host, or to us */
    if (pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0)
        return mod_PASS;

    /* TODO: implementation */

    return mod_PASS;
}
예제 #25
0
파일: sm.c 프로젝트: norulesbozo/jabberd2
void sm_delete(sess_t sess, bres_t res) {
    sx_nad_write(sess->c2s->router, _sm_build_route(sess, res, "delete", jid_user(res->jid), NULL));
}
예제 #26
0
파일: sm.c 프로젝트: norulesbozo/jabberd2
void sm_create(sess_t sess, bres_t res) {
    _sm_generate_id(sess, res, "create");

    sx_nad_write(sess->c2s->router, _sm_build_route(sess, res, "create", jid_user(res->jid), res->sm_request));
}
예제 #27
0
파일: mod_vacation.c 프로젝트: zipo/zipo
static mod_ret_t _vacation_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    module_t mod = mi->mod;
    vacation_t v = sess->user->module_data[mod->index];
    int ns, start, end, msg;
    char dt[30];
    pkt_t res;
    os_t os;
    os_object_t o;

    /* we only want to play with vacation iq packets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_VACATION)
        return mod_PASS;

    /* if it has a to, throw it out */
    if(pkt->to != NULL)
        return -stanza_err_BAD_REQUEST;

    /* get */
    if(pkt->type == pkt_IQ) {
        if(v->msg == NULL) {
            res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
            pkt_id(pkt, res);
            pkt_free(pkt);

            pkt_sess(res, sess);

            return mod_HANDLED;
        }

        ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL);

        if(v->start != 0) {
            datetime_out(v->start, dt_DATETIME, dt, 30);
            nad_insert_elem(pkt->nad, 2, ns, "start", dt);
        } else
            nad_insert_elem(pkt->nad, 2, ns, "start", NULL);

        if(v->end != 0) {
            datetime_out(v->end, dt_DATETIME, dt, 30);
            nad_insert_elem(pkt->nad, 2, ns, "end", dt);
        } else
            nad_insert_elem(pkt->nad, 2, ns, "end", NULL);

        nad_insert_elem(pkt->nad, 2, ns, "message", v->msg);

        pkt_tofrom(pkt);
        nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);
            
        pkt_sess(pkt, sess);

        return mod_HANDLED;
    }

    /* set */
    ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL);

    start = nad_find_elem(pkt->nad, 2, ns, "start", 1);
    end = nad_find_elem(pkt->nad, 2, ns, "end", 1);
    msg = nad_find_elem(pkt->nad, 2, ns, "message", 1);

    if(start < 0 || end < 0 || msg < 0) {
        /* forget */
        if(v->msg != NULL) {
            free(v->msg);
            v->msg = NULL;
        }
        v->start = 0;
        v->end = 0;

        storage_delete(mi->sm->st, "vacation-settings", jid_user(sess->jid), NULL);

        res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
        pkt_id(pkt, res);
        pkt_free(pkt);

        pkt_sess(res, sess);

        return mod_HANDLED;
    }

    if(NAD_CDATA_L(pkt->nad, start) > 0) {
        strncpy(dt, NAD_CDATA(pkt->nad, start), (30 < NAD_CDATA_L(pkt->nad, start) ? 30 : NAD_CDATA_L(pkt->nad, start)));
        v->start = datetime_in(dt);
    } else
        v->start = 0;

    if(NAD_CDATA_L(pkt->nad, end) > 0) {
        strncpy(dt, NAD_CDATA(pkt->nad, end), (30 < NAD_CDATA_L(pkt->nad, end) ? 30 : NAD_CDATA_L(pkt->nad, end)));
        v->end = datetime_in(dt);
    } else
        v->end = 0;

    v->msg = (char *) malloc(sizeof(char) * (NAD_CDATA_L(pkt->nad, msg) + 1));
    strncpy(v->msg, NAD_CDATA(pkt->nad, msg), NAD_CDATA_L(pkt->nad, msg));
    v->msg[NAD_CDATA_L(pkt->nad, msg)] = '\0';

    os = os_new();
    o = os_object_new(os);
    os_object_put(o, "start", &v->start, os_type_INTEGER);
    os_object_put(o, "end", &v->end, os_type_INTEGER);
    os_object_put(o, "message", v->msg, os_type_STRING);

    if(storage_replace(mod->mm->sm->st, "vacation-settings", jid_user(sess->user->jid), NULL, os) != st_SUCCESS) {
        free(v->msg);
        v->msg = NULL;
        v->start = 0;
        v->end = 0;
        return -stanza_err_INTERNAL_SERVER_ERROR;
    }
    
    res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL);
    pkt_id(pkt, res);
    pkt_free(pkt);

    pkt_sess(res, sess);

    return mod_HANDLED;
}
예제 #28
0
static mod_ret_t _iq_private_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {
    module_t mod = mi->mod;
    int ns, elem, target, targetns;
    st_ret_t ret;
    char filter[4096];
    os_t os;
    os_object_t o;
    nad_t nad;
    pkt_t result;
    sess_t sscan;

    /* only handle private sets and gets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVATE)
        return mod_PASS;

    /* we're only interested in no to, to our host, or to us */
    if(pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0)
        return mod_PASS;

    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVATE, NULL);
    elem = nad_find_elem(pkt->nad, 1, ns, "query", 1);

    /* find the first child */
    target = elem + 1;
    while(target < pkt->nad->ecur)
    {
        if(pkt->nad->elems[target].depth > pkt->nad->elems[elem].depth)
            break;

        target++;
    }

    /* not found, so we're done */
    if(target == pkt->nad->ecur)
        return -stanza_err_BAD_REQUEST;

    /* find the target namespace */
    targetns = NAD_ENS(pkt->nad, target);

    /* gotta have a namespace */
    if(targetns < 0)
    {
        log_debug(ZONE, "no namespace specified");
        return -stanza_err_BAD_REQUEST;
    }

    log_debug(ZONE, "processing private request for %.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    /* get */
    if(pkt->type == pkt_IQ) {
#ifdef ENABLE_EXPERIMENTAL
        /* remember that this resource requested the namespace */
        if(sess->module_data[mod->index] == NULL) {
            /* create new hash if necesary */
            sess->module_data[mod->index] = xhash_new(101);
            pool_cleanup(sess->p, (void (*))(void *) xhash_free, sess->module_data[mod->index]);
        }
        xhash_put(sess->module_data[mod->index], pstrdupx(sess->p, NAD_NURI(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns)), (void *) 1);
#endif
        snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
        ret = storage_get(sess->user->sm->st, "private", jid_user(sess->jid), filter, &os);
        switch(ret) {
            case st_SUCCESS:
                if(os_iter_first(os)) {
                    o = os_iter_object(os);
                    if(os_object_get_nad(os, o, "xml", &nad)) {
                        result = pkt_new(sess->user->sm, nad_copy(nad));
                        if(result != NULL) {
                            nad_set_attr(result->nad, 1, -1, "type", "result", 6);

                            pkt_id(pkt, result);

                            pkt_sess(result, sess);

                            pkt_free(pkt);

                            os_free(os);
                
                            return mod_HANDLED;
                        }
                    }
                }

                os_free(os);

                /* drop through */
                log_debug(ZONE, "storage_get succeeded, but couldn't make packet, faking st_NOTFOUND");

            case st_NOTFOUND:

                log_debug(ZONE, "namespace not found, returning");

                /*
                 * !!! really, we should just return a 404. 1.4 just slaps a
                 *     result on the packet and sends it back. hurrah for
                 *     legacy namespaces.
                 */
                nad_set_attr(pkt->nad, 1, -1, "type", "result", 6);

                pkt_sess(pkt_tofrom(pkt), sess);
                
                return mod_HANDLED;

            case st_FAILED:
                return -stanza_err_INTERNAL_SERVER_ERROR;

            case st_NOTIMPL:
                return -stanza_err_FEATURE_NOT_IMPLEMENTED;
        }
    }

    os = os_new();
    o = os_object_new(os);

    snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
    os_object_put(o, "ns", filter, os_type_STRING);
    os_object_put(o, "xml", pkt->nad, os_type_NAD);

    snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));

    ret = storage_replace(sess->user->sm->st, "private", jid_user(sess->jid), filter, os);
    os_free(os);

    switch(ret) {
        case st_FAILED:
            return -stanza_err_INTERNAL_SERVER_ERROR;

        case st_NOTIMPL:
            return -stanza_err_FEATURE_NOT_IMPLEMENTED;

        default:
            /* create result packet */
            result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL);
            pkt_id(pkt, result);
            /* and flush it to the session */
            pkt_sess(result, sess);
#ifdef ENABLE_EXPERIMENTAL
            /* push it to all resources that read this xmlns item */
            snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns));
            for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) {
                /* skip our resource and those that didn't read any private-storage */
                if(sscan == sess || sscan->module_data[mod->index] == NULL)
                    continue;

                /* check whether namespace was read */
                if(xhash_get(sscan->module_data[mod->index], filter)) {
                    result = pkt_dup(pkt, jid_full(sscan->jid), NULL);
                    if(result->from != NULL) {
                        jid_free(result->from);
                        nad_set_attr(result->nad, 1, -1, "from", NULL, 0);
                    }
                    pkt_id_new(result);
                    pkt_sess(result, sscan);
                }
            }
#endif
            /* finally free the packet */
            pkt_free(pkt);
            return mod_HANDLED;
    }

    /* we never get here */
    return 0;
}
예제 #29
0
파일: sessions.c 프로젝트: smokku/wpjabber
/*
 *  js_session_new -- creates a new session, registers the resource for it
 *
 *  Sets up all the data associated with the new session, then send it a
 *  start spacket, which basically notifies all modules about the new session
 *
 *  returns
 *	a pointer to the new session
 */
session js_session_new(jsmi si, dpacket dp)
{
	pool p;
	session s, cur;
	udata u;
	int i;
	char routeres[10];

	/* screen out illegal calls */
	if (dp == NULL || dp->id->user == NULL || dp->id->resource == NULL
	    || xmlnode_get_attrib(dp->x, "from") == NULL)
		return NULL;

	if ((u = js_user(si, dp->id, 0)) == NULL)
		return NULL;

	if (u->scount >= MAX_USER_SESSIONS) {
		THREAD_DEC(u->ref);
		return NULL;
	}


	log_debug("session_create %s", jid_full(dp->id));

	/* create session */
	p = pool_heap(1024);
	s = pmalloco(p, sizeof(struct session_struct));
	s->p = p;
	s->si = si;

	/* save authorative remote session id */
	s->sid = jid_new(p, xmlnode_get_attrib(dp->x, "from"));

	/* session identity */
	s->id = jid_new(p, jid_full(dp->id));
	/* id bez resource */
	s->uid = jid_user(s->id);
	s->route = jid_new(p, jid_full(dp->id));
	snprintf(routeres, 9, "%X", s);
	jid_set(s->route, routeres, JID_RESOURCE);
	s->res = pstrdup(p, dp->id->resource);
	s->u = u;

	jid_full(s->sid);
	jid_full(s->uid);
	jid_full(s->id);
	jid_full(s->route);

	{
		register char *text;
		text = xmlnode_get_attrib(dp->x, "ip");
		if (text) {
			s->ip =
			    pstrdup(s->p, xmlnode_get_attrib(dp->x, "ip"));
			xmlnode_hide_attrib(dp->x, "ip");
		} else
			s->ip = "none";
	}

	/* default settings */
	s->exit_flag = 0;
	s->roster = 0;
	s->priority = -129;
	s->presence = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL);
	xmlnode_put_attrib(s->presence, "from", jid_full(s->id));
	s->c_in = s->c_out = 0;

	for (i = 0; i < es_LAST; i++)
		s->events[i] = NULL;

	SEM_LOCK(u->sem);

	if (u->sessions != NULL) {
		s->q = get_mtq_queue(si, u->sessions->q);

		for (cur = u->sessions; cur != NULL; cur = cur->next)
			if (j_strcmp(dp->id->resource, cur->res) == 0)
				js_session_end_nosem(cur,
						     "Replaced by new connection");
	} else {
		s->q = get_mtq_queue(si, NULL);
	}

	/* make sure we're linked with the user */
	s->next = s->u->sessions;
	s->u->sessions = s;
	s->u->scount++;

	SEM_UNLOCK(u->sem);

	/* session start */
	{
		packet_thread_p pt;
		pt = malloc(sizeof(packet_thread_t));
		pt->s = s;
		pt->type = 0;
		fast_mtq_send(s->q->mtq, pt);
	}

	THREAD_DEC(u->ref);
	return s;
}
예제 #30
0
파일: mod_vacation.c 프로젝트: zipo/zipo
static void _vacation_user_delete(mod_instance_t mi, jid_t jid) {
    log_debug(ZONE, "deleting vacations settings for %s", jid_user(jid));

    storage_delete(mi->sm->st, "vacation-settings", jid_user(jid), NULL);
}