Пример #1
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;
}
Пример #2
0
/* session thread */
mreturn mod_presence_in(mapi m, void *arg)
{
	modpres mp = (modpres) arg;
	xmlnode pres;

	if (m->packet->type != JPACKET_PRESENCE)
		return M_IGNORE;

	log_debug("incoming filter for %s", jid_full(m->s->id));

	if (jpacket_subtype(m->packet) == JPACKET__PROBE) {
		/* reply with our presence */
		if (m->s->presence == NULL) {
			log_debug("probe from %s and no presence to return", jid_full(m->packet->from));
		} else if (!mp->invisible && js_trust(m->user, m->packet->from) && !_mod_presence_search(m->packet->from, mp->I)) {
			/* compliment of I in T */
			log_debug("got a probe, responding to %s", jid_full(m->packet->from));
			pres = xmlnode_dup(m->s->presence);
			xmlnode_put_attrib(pres, "to", jid_full(m->packet->from));
			js_session_from(m->s, jpacket_new(pres));
		} else if (mp->invisible && js_trust(m->user, m->packet->from) && _mod_presence_search(m->packet->from, mp->A)) {
			/* when invisible, intersection of A and T */
			log_debug("got a probe when invisible, responding to %s", jid_full(m->packet->from));
			pres = jutil_presnew(JPACKET__AVAILABLE, jid_full(m->packet->from), NULL);
			js_session_from(m->s, jpacket_new(pres));
		} else {
			log_debug("%s attempted to probe by someone not qualified", jid_full(m->packet->from));
		}
		xmlnode_free(m->packet->x);
		return M_HANDLED;
	}

	if (jid_cmp(m->packet->from, m->s->id) == 0) {
		/* this is our presence, don't send to ourselves */
		xmlnode_free(m->packet->x);
		return M_HANDLED;
	}

	/* if a presence packet bounced, remove from the A list */
	if (jpacket_subtype(m->packet) == JPACKET__ERROR)
		mp->A = _mod_presence_whack(m->packet->from, mp->A);

	/* doh! this is a user, they should see invisibles as unavailables */
	if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE)
		xmlnode_put_attrib(m->packet->x, "type", "unavailable");

	return M_PASS;
}
Пример #3
0
/* handle a packet from jabberd */
result at_phandler(instance i,dpacket p,void *arg)
{
    int ret;
    ati ti;
    at_mtq_data amd;

    if(i == NULL || p == NULL) 
        return r_ERR;

    ti = (ati)arg;

    switch(p->type)
    {
    case p_NONE:
    case p_NORM:
        log_debug(ZONE, "[AT] we got a packet from jabberd: %s", xmlnode2str(p->x));
        amd = pmalloco(p->p, sizeof(_at_mtq_data));
        amd->jp = jpacket_new(p->x);
        amd->p = p->p;
        amd->ti = ti;

        mtq_send(NULL, p->p, at_parse_packet, (void *)amd);
        return r_DONE;
    default:
        log_debug(ZONE, "[AT] ignoring packet from jabberd: %s", xmlnode2str(p->x));
        return r_PASS;
    }
}
Пример #4
0
/* thread safe with sem */
mreturn mod_presence_deliver(mapi m, void *arg)
{
	session cur;

	if (m->packet->type != JPACKET_PRESENCE)
		return M_IGNORE;

	log_debug("deliver phase");

	/* only if we HAVE a user, and it was sent to ONLY the user@server, and there is at least one session available */
	if (m->user != NULL && m->packet->to->resource == NULL && js_session_primary_all_sem(m->user) != NULL) {
		log_debug("broadcasting to %s", m->user->user);

		/* broadcast */
		for (cur = m->user->sessions; cur != NULL; cur = cur->next) {
			if (cur->priority < -128)
				continue;
			js_session_to(cur, jpacket_new(xmlnode_dup(m->packet->x)));
		}
		SEM_UNLOCK(m->user->sem);

		if (jpacket_subtype(m->packet) != JPACKET__PROBE) {
			/* probes get handled by the offline thread as well? */
			xmlnode_free(m->packet->x);
			return M_HANDLED;
		}
	}

	return M_PASS;
}
Пример #5
0
void _mod_presence_broadcast_trusted(session s, jid notify, xmlnode x)
{
	jid cur;
	xmlnode pres;

	for (cur = notify; cur != NULL; cur = cur->next) {
		if (!js_istrusted(s->u, cur))
			continue;	/* perform insersection search, must be in both */
		s->c_out++;
		pres = xmlnode_dup(x);
		xmlnode_put_attrib(pres, "to", jid_full(cur));

		/* send it to POSTOUT for filter purposes */
		js_post_out_main(s, jpacket_new(pres));
	}
}
Пример #6
0
result mt_receive(instance i, dpacket d, void *arg)
{
    jpacket jp;
    mti ti;
    session s;

    switch(d->type)
    {
    case p_NONE:
    case p_NORM:
        jp = jpacket_new(d->x);
        if (jp->from && jp->from->user && jp->type != JPACKET_UNKNOWN &&
            jpacket_subtype(jp) != JPACKET__ERROR)
        {
            mti ti = (mti) arg;
            session s = mt_session_find(ti,jp->from);

            lowercase(jp->from->server);
            lowercase(jp->from->user);


            if (s != NULL)
                mt_session_process(s,jp);
            else
                mt_unknown_process(ti,jp);
        }
        else
        {
            log_warn(NULL,"Invalid packet");
            xmlnode_free(d->x);
        }
        break;

    default:
        return r_ERR;

    }

    return r_DONE;
}
Пример #7
0
/* any thread */
result js_packet(instance i, dpacket p, void *arg)
{
	jsmi si = (jsmi) arg;
	jpacket jp = NULL;
	session s = NULL;
	packet_thread_p pt;
	udata u;

	char *type, *authto;

	log_debug("incoming packet %s", xmlnode2str(p->x));

	/* if this is a routed packet */
	if (p->type == p_ROUTE) {
		type = xmlnode_get_attrib(p->x, "type");

		/* new session requests */
		if (j_strcmp(type, "session") == 0) {
			js_session_new_mtq(si, p);
			return r_DONE;
		}

		/* get the internal jpacket */
		if (xmlnode_get_firstchild(p->x) != NULL)	/* XXX old libjabber jpacket_new() wasn't null safe, this is just safety */
			jp = jpacket_new(xmlnode_get_firstchild(p->x));


		/* auth/reg requests */
		if (jp != NULL && j_strcmp(type, "auth") == 0) {
			/* check and see if we're configured to forward auth packets for processing elsewhere */
			if ((authto =
			     xmlnode_get_data(js_config(si, "auth"))) !=
			    NULL) {
				xmlnode_put_attrib(p->x, "oto", xmlnode_get_attrib(p->x, "to"));	/* preserve original to */
				xmlnode_put_attrib(p->x, "to", authto);
				deliver(dpacket_new(p->x), i);
				return r_DONE;
			}

			/* internally, hide the route to/from addresses on the authreg request */
			xmlnode_put_attrib(jp->x, "to",
					   xmlnode_get_attrib(p->x, "to"));
			xmlnode_put_attrib(jp->x, "from",
					   xmlnode_get_attrib(p->x,
							      "from"));
			xmlnode_put_attrib(jp->x, "route",
					   xmlnode_get_attrib(p->x,
							      "type"));
			jpacket_reset(jp);
			jp->aux1 = (void *) si;

			pt = pmalloco(jp->p, sizeof(packet_thread_t));
			pt->jp = jp;
			fast_mtq_send(si->mtq_authreg, pt);
			return r_DONE;
		}

		/* if it's an error */
		if (j_strcmp(type, "error") == 0) {

			/* look for users online */
			u = js_user(si, p->id, 1);
			if (u == NULL) {
				/* if this was a message,
				   it should have been delievered to that session, store offline */
				if (jp != NULL
				    && jp->type == JPACKET_MESSAGE) {
					pt = pmalloco(jp->p,
						      sizeof
						      (packet_thread_t));
					pt->jp = jp;
					fast_mtq_send(si->mtq_deliver, pt);
					return r_DONE;
				}

				xmlnode_free(p->x);
				return r_DONE;
				/*
				   log_notice(p->host,
				   "Bouncing packet intended for nonexistant user: %s",
				   xmlnode2str(p->x));
				   deliver_fail(dpacket_new(p->x), "Invalid User");
				   return r_DONE;
				 */
			}

			if (p->id->resource != NULL) {
				SEM_LOCK(u->sem);
				for (s = u->sessions; s != NULL;
				     s = s->next)
					if (j_strcmp
					    (p->id->resource,
					     s->route->resource) == 0)
						break;
				SEM_UNLOCK(u->sem);

				if (s != NULL) {
					s->sid = NULL;	/* they generated the error,
							   no use in sending there anymore! */
					js_session_end(s, "Disconnected");
				}
			} else {
				session temp;
				/* a way to boot an entire user off */
				SEM_LOCK(u->sem);
				for (s = u->sessions; s != NULL;) {
					temp = s;
					s = s->next;
					js_session_end_nosem(temp,
							     "Removed");
				}
				u->pass = NULL;	/* so they can't log back in */

				SEM_UNLOCK(u->sem);

				xmlnode_free(p->x);
				THREAD_DEC(u->ref);
				return r_DONE;
			}

			THREAD_DEC(u->ref);

			/* if this was a message,
			   it should have been delievered to that session, store offline */
			if (jp != NULL && jp->type == JPACKET_MESSAGE) {
				pt = pmalloco(jp->p,
					      sizeof(packet_thread_t));
				pt->jp = jp;
				fast_mtq_send(si->mtq_deliver, pt);
				return r_DONE;
			}

			/* drop and return */
			if (xmlnode_get_firstchild(p->x) != NULL)
				log_notice(p->host,
					   "Dropping a bounced session packet to %s",
					   jid_full(p->id));

			xmlnode_free(p->x);
			return r_DONE;
		}

		/* uhh, empty packet, *shrug* */
		if (jp == NULL) {
			log_notice(p->host,
				   "Dropping an invalid or empty route packet: %s",
				   xmlnode2str(p->x), jid_full(p->id));
			xmlnode_free(p->x);
			return r_DONE;
		}

		/* ============================================================== */


		/* attempt to locate the session by matching the special resource */
		u = js_user(si, p->id, 1);
		if (u == NULL) {
			/* only when route packet to users not online */
			pt = pmalloco(p->p, sizeof(packet_thread_t));
			pt->p = p;
			pt->jp = jp;
			fast_mtq_send(si->mtq_deliver, pt);
			return r_DONE;
		}

		/* user is online :) */
		SEM_LOCK(u->sem);
		for (s = u->sessions; s != NULL; s = s->next)
			if (j_strcmp(p->id->resource, s->route->resource)
			    == 0)
				break;
		SEM_UNLOCK(u->sem);

		THREAD_DEC(u->ref);

		if (s != NULL) {	/* just pass to the session normally */
			js_session_from(s, jp);
			return r_DONE;
		}

		log_notice(p->host,
			   "Bouncing %s packet intended for session %s",
			   xmlnode_get_name(jp->x), jid_full(p->id));
		deliver_fail(dpacket_new(p->x), "Invalid Session");
		return r_DONE;
	}

	/* normal server-server packet, should we make sure it's not spoofing us?  if so, if ghash_get(p->to->server) then bounce w/ security error */

	jp = jpacket_new(p->x);
	if (jp == NULL) {
		log_warn(p->host, "Dropping invalid incoming packet: %s",
			 xmlnode2str(p->x));
		xmlnode_free(p->x);
		return r_DONE;
	}

	pt = pmalloco(jp->p, sizeof(packet_thread_t));
	pt->jp = jp;
	fast_mtq_send(si->mtq_deliver, pt);
	return r_DONE;
}
Пример #8
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;
}
Пример #9
0
/* session thread */
mreturn mod_presence_out(mapi m, void *arg)
{
	xmlnode pnew, delay, pold;
	modpres mp = (modpres) arg;
	session cur = NULL;
	int oldpri, newpri;
	char *priority;

	if (m->packet->type != JPACKET_PRESENCE)
		return M_IGNORE;

	if (m->packet->to != NULL
	    || jpacket_subtype(m->packet) == JPACKET__PROBE
	    || jpacket_subtype(m->packet) == JPACKET__ERROR)
		return M_PASS;

	log_debug("new presence from %s of %s", jid_full(m->s->id), xmlnode2str(m->packet->x));

	/* pre-existing conditions (no, we are not an insurance company) */
	oldpri = m->s->priority;

	/* check that the priority is in the valid range */
	priority = xmlnode_get_tag_data(m->packet->x, "priority");
	if (priority == NULL) {
		newpri = 0;
	} else {
		newpri = j_atoi(priority, 0);
		if (newpri < -128 || newpri > 127) {
			log_notice("mod_presence", "got presence with invalid priority value from %s", jid_full(m->s->id));
			xmlnode_free(m->packet->x);
			return M_HANDLED;
		}
	}

	/* invisible mode is special, don't you wish you were special too? */
	if (jpacket_subtype(m->packet) == JPACKET__INVISIBLE) {
		log_debug("handling invisible mode request");

		/* if we get this and we're available, it means go unavail first then reprocess this packet, nifty trick :) */
		if (oldpri >= -128) {
			js_session_from(m->s,
					jpacket_new(jutil_presnew
						    (JPACKET__UNAVAILABLE,
						     NULL,
						     xmlnode_get_tag_data(m->packet->x,"status")
						    )));
			js_session_from(m->s, m->packet);
			return M_HANDLED;
		}

		/* now, pretend we come online :) */
		/* (this is the handling of the reinjected invisible presence
		 * or an initial invisible presence) */
		mp->invisible = 1;
		mod_presence_roster(m, NULL);	/* send out probes to users we are subscribed to */
		m->s->priority = newpri;

		/* store presence in xdb? */
		if (mp->conf->pres_to_xdb > 0)
			mod_presence_store(m);

		xmlnode_free(m->packet->x);	/* we do not broadcast invisible presences without a to attribute */

		return M_HANDLED;
	}

	/* our new presence */
	pnew = xmlnode_dup(m->packet->x);

	/* store presence in xdb? */
	if (mp->conf->pres_to_xdb > 0)
		mod_presence_store(m);

	/* stamp the sessions presence */
	delay = xmlnode_insert_tag(pnew, "x");
	xmlnode_put_attrib(delay, "xmlns", NS_DELAY);
	xmlnode_put_attrib(delay, "from", jid_full(m->s->id));
	xmlnode_put_attrib(delay, "stamp", jutil_timestamp());

	/* our old presence */
	pold = m->s->presence;
	m->s->presence = pnew;
	m->s->priority = jutil_priority(pnew);

	log_debug("presence oldp %d newp %d", oldpri, m->s->priority);

	/* if we're going offline now, let everyone know */
	if (m->s->priority < -128) {
		/* jutil_priority returns -129 in case the "type" attribute is missing */
		if (!mp->invisible)
			/* bcc's don't get told if we were invisible */
			_mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL);
		_mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL);
		_mod_presence_broadcast(m->s, mp->I, m->packet->x, NULL);

		/* reset vars */
		mp->invisible = 0;
		mp->A->next = NULL;
		mp->I = NULL;

		xmlnode_free(m->packet->x);
		xmlnode_free(pold);
		return M_HANDLED;
	}

	/* available presence updates, intersection of A and T */
	if (oldpri >= -128 && !mp->invisible) {
		_mod_presence_broadcast_trusted(m->s, mp->A, m->packet->x);
		xmlnode_free(m->packet->x);
		xmlnode_free(pold);
		return M_HANDLED;
	}

	/* at this point we're coming out of the closet */
	mp->invisible = 0;

	/* make sure we get notified for any presence about ourselves */
	/* XXX: the following is the original code: it caused existing presences
	 * to be stamped several times and the presence to be sent out twice.

	 pnew = jutil_presnew(JPACKET__PROBE,jid_full(m->s->uid),NULL);
	 xmlnode_put_attrib(pnew,"from",jid_full(m->s->uid));
	 js_session_from(m->s, jpacket_new(pnew));

	 */
	/* XXX: I think this should be okay as well: */

	/* send us all presences of our other resources */
	for (cur = m->user->sessions; cur != NULL; cur = cur->next) {
		pool pool_for_existing_presence = NULL;
		xmlnode duplicated_presence = NULL;
		jpacket packet = NULL;

		/* skip our own session (and sanity check) */
		if (cur == m->s || cur->presence == NULL) {
			continue;
		}

		/* send the presence to us: we need a new pool as js_session_to() will free the packet's pool  */
		pool_for_existing_presence = pool_new();
		duplicated_presence =
		    xmlnode_dup_pool(pool_for_existing_presence,
				     cur->presence);
		xmlnode_put_attrib(duplicated_presence, "to",
				   jid_full(m->user->id));
		packet = jpacket_new(duplicated_presence);
		js_session_to(m->s, packet);
	}

	/* probe s10ns and populate A */
	mod_presence_roster(m, mp->A);

	/* we broadcast this baby! */
	_mod_presence_broadcast(m->s, mp->conf->bcc, m->packet->x, NULL);
	_mod_presence_broadcast(m->s, mp->A, m->packet->x, NULL);

	xmlnode_free(m->packet->x);
	xmlnode_free(pold);

	return M_HANDLED;
}