/* always deliver threads */ static void js_outgoing_packet(jsmi si, jpacket jp, dpacket p) { session s = NULL; udata u; /* attempt to locate the session by matching the special resource */ u = js_user(si, p->id, 0); if (u == NULL) { log_notice(p->host, "Bouncing packet intended for nonexistant user: %s", xmlnode2str(p->x)); deliver_fail(dpacket_new(p->x), "Invalid User"); return; } 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; } 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"); }
mreturn mod_log_archiver(mapi m, void *arg) { jid svcs = (jid) arg; xmlnode x; char ts[101]; struct tm now; unsigned long ltime; if (m->packet->type != JPACKET_MESSAGE) return M_IGNORE; log_debug("archiving message"); /* get a copy wrapped w/ a route and stamp it w/ a type='archive' (why not?) */ x = xmlnode_wrap(xmlnode_dup(m->packet->x), "route"); xmlnode_put_attrib(x, "type", "archive"); /* Mark the route with an direction attribute */ switch (m->e) { case es_IN: xmlnode_put_attrib(x, "direction", "in"); break; case es_OUT: xmlnode_put_attrib(x, "direction", "out"); break; } /* Mark the route with a timeStamp attribute */ time(<ime); #ifdef WIN32 now = *localtime(<ime); #else localtime_r(<ime, &now); #endif strftime((char *) ts, 100, "%m/%d/%Y %H:%M:%S", &now); xmlnode_put_attrib(x, "stamp", ts); /* if there's more than one service, copy to the others */ for (; svcs->next != NULL; svcs = svcs->next) { xmlnode_put_attrib(x, "to", jid_full(svcs)); deliver(dpacket_new(xmlnode_dup(x)), NULL); } /* send off to the last (or only) one */ xmlnode_put_attrib(x, "to", jid_full(svcs)); deliver(dpacket_new(x), NULL); return M_PASS; }
void con_room_forward_decline(cnr room, jpacket jp, xmlnode decline) { cnu user; jid user_jid; if (room == NULL || decline == NULL || jp == NULL) { log_warn(NAME, "[%s] Aborting - NULL attribute found", FZONE); xmlnode_free(jp->x); return; } user_jid=jid_new(decline->p,xmlnode_get_attrib(decline,"to")); if ((room->invitation == 1 && !is_member(room, jp->from) && !is_owner(room, jp->from)) || user_jid == NULL) { log_warn(NAME, "[%s] Aborting - User is not allowed to send a decline", FZONE); jutil_error(jp->x, TERROR_MUC_OUTSIDE); deliver(dpacket_new(jp->x), NULL); return; } if (user_jid->resource == NULL) { log_warn(NAME, "[%s] Aborting - cannot send back decline, bare jid found", FZONE); return; } if (room->visible == 1) { user = g_hash_table_lookup(room->remote, jid_full(jid_fix(user_jid))); } else { user = g_hash_table_lookup(room->local, user_jid->resource); } if (user == NULL){ log_warn(NAME, "[%s] Aborting - Decline recipient is not in the room", FZONE); jutil_error(jp->x, TERROR_MUC_OUTSIDE); deliver(dpacket_new(jp->x), NULL); return; } log_debug(NAME, "[%s] Sending invitation decline", FZONE); xmlnode_put_attrib(decline, "from", jid_full(jp->from)); xmlnode_hide_attrib(decline, "to"); xmlnode_put_attrib(jp->x, "to", jid_full(user->realid)); xmlnode_put_attrib(jp->x, "from", jid_full(room->id)); log_debug(NAME, "[%s] >>>%s<<<", FZONE, xmlnode2str(jp->x)); deliver(dpacket_new(jp->x), NULL); return; }
/* actually deliver the xdb request */ void xdb_deliver(instance i, xdbcache xc, int another_thread) { xmlnode x; char ids[15]; x = xmlnode_new_tag("xdb"); if(xc->set) { xmlnode_put_attrib(x,"type","set"); xmlnode_insert_tag_node(x,xc->data); /* copy in the data */ if(xc->act != NULL) xmlnode_put_attrib(x,"action",xc->act); if(xc->match != NULL) xmlnode_put_attrib(x,"match",xc->match); } else { xmlnode_put_attrib(x,"type","get"); } xmlnode_put_attrib(x,"to",jid_full(xc->owner)); xmlnode_put_attrib(x,"from",i->id); xmlnode_put_attrib(x,"ns",xc->ns); sprintf(ids,"%d",xc->id); xmlnode_put_attrib(x,"id",ids); /* to track response */ if (another_thread) { xdb_resend cur = pmalloco(xmlnode_pool(x),sizeof(_xdb_resend)); cur->x = x; cur->i = i; mtq_send(NULL,NULL,resend_xdb,(void *)cur); } else { deliver(dpacket_new(x), i); } }
/* NOTE: any jpacket sent to deliver *MUST* match jpacket_new(p->x), * jpacket is simply a convenience wrapper */ void js_deliver(jsmi si, jpacket p) { if (p->to == NULL) { log_warn(NULL, "jsm: Invalid Recipient, returning data %s", xmlnode2str(p->x)); js_bounce(si, p->x, TERROR_BAD); return; } if (p->from == NULL) { log_warn(NULL, "jsm: Invalid Sender, discarding data %s", xmlnode2str(p->x)); xmlnode_free(p->x); return; } log_debug("deliver(to[%s],from[%s],type[%d],packet[%s])", jid_full(p->to), jid_full(p->from), p->type, xmlnode2str(p->x)); /* is it our */ if (j_strcmp(si->host, p->to->server) == 0) { js_deliver_local(si, p); return; } deliver(dpacket_new(p->x), si->i); }
result base_to_deliver(instance id, dpacket p, void *arg) { char *log_data = xmlnode_get_data(p->x); char *subject; xmlnode message; if (log_data == NULL) return r_ERR; message = xmlnode_new_tag("message"); xmlnode_insert_cdata(xmlnode_insert_tag(message, "body"), log_data, -1); subject = spools(xmlnode_pool(message), "Log Packet from ", xmlnode_get_attrib(p->x, "from"), xmlnode_pool(message)); xmlnode_insert_cdata(xmlnode_insert_tag(message, "thread"), shahash(subject), -1); xmlnode_insert_cdata(xmlnode_insert_tag(message, "subject"), subject, -1); xmlnode_put_attrib(message, "from", xmlnode_get_attrib(p->x, "from")); xmlnode_put_attrib(message, "to", (char *) arg); deliver(dpacket_new(message), id); pool_free(p->p); return r_DONE; }
void dnsrv_resend(xmlnode pkt, char *ip, char *to) { if(ip != NULL) { pkt = xmlnode_wrap(pkt,"route"); xmlnode_put_attrib(pkt, "to", to); xmlnode_put_attrib(pkt, "ip", ip); }else{ jutil_error(pkt, (terror){502, "Unable to resolve hostname."}); xmlnode_put_attrib(pkt, "iperror", ""); } deliver(dpacket_new(pkt),NULL); }
/* delivers a route packet to all listeners for this session */ static void js_session_route(session s, xmlnode in) { /* NULL means this is an error from the session ending */ if (in == NULL) { in = xmlnode_new_tag("route"); xmlnode_put_attrib(in, "type", "error"); xmlnode_put_attrib(in, "error", "Disconnected"); } else { in = xmlnode_wrap(in, "route"); } xmlnode_put_attrib(in, "from", jid_full(s->route)); xmlnode_put_attrib(in, "to", jid_full(s->sid)); deliver(dpacket_new(in), s->si->i); }
/* always deliver threads */ inline static void js_session_new_mtq(jsmi si, dpacket p) { session s; if ((s = js_session_new(si, p)) == NULL) { /* session start failed */ log_warn(p->host, "Unable to create session %s", jid_full(p->id)); xmlnode_put_attrib(p->x, "type", "error"); xmlnode_put_attrib(p->x, "error", "Session Failed"); } else { /* reset to the routed id for this session for the reply below */ xmlnode_put_attrib(p->x, "to", jid_full(s->route)); } /* reply */ jutil_tofrom(p->x); deliver(dpacket_new(p->x), si->i); }
void deliver_fail(dpacket p, char *err) { terror t; /* normal packet bounce */ if(j_strcmp(xmlnode_get_attrib(p->x,"type"),"error") == 0) { /* can't bounce an error */ log_warn(p->host,"dropping a packet to %s from %s: %s",xmlnode_get_attrib(p->x,"to"),xmlnode_get_attrib(p->x,"from"),err); pool_free(p->p); } else { log_warn(p->host,"bouncing a packet to %s from %s: %s",xmlnode_get_attrib(p->x,"to"),xmlnode_get_attrib(p->x,"from"),err); /* turn into an error */ if(err == NULL) { jutil_error(p->x,TERROR_EXTERNAL); } else { t.code = 502; strcpy(t.msg,err); strcpy(t.condition, "service-unavailable"); strcpy(t.type, "wait"); jutil_error(p->x,t); } deliver(dpacket_new(p->x),NULL); } }
/** Resend packet in other thread */ void resend_xdb(void *arg) { xdb_resend cur = (xdb_resend)arg; deliver(dpacket_new(cur->x), cur->i); }
/* 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; }
void con_room_send_invite(cnu sender, xmlnode node) { xmlnode result; xmlnode element; xmlnode invite; xmlnode pass; char *body, *user, *reason, *inviter; cnr room; pool p; if(sender == NULL || node == NULL) { log_warn(NAME, "[%s] Aborting - NULL attribute found", FZONE); return; } log_debug(NAME, "[%s] Sending room invite", FZONE); room = sender->room; invite = xmlnode_get_tag(node, "invite"); user = xmlnode_get_attrib(invite, "to"); reason = xmlnode_get_tag_data(invite, "reason"); p = xmlnode_pool(node); if(room->visible == 1) { inviter = jid_full(sender->realid); } else { inviter = jid_full(sender->localid); } xmlnode_put_attrib(invite, "from", inviter); xmlnode_hide_attrib(invite, "to"); if(reason == NULL) { reason = spools(p, "None given", p); } body = spools(p, "You have been invited to the ", jid_full(room->id), " room by ", inviter, "\nReason: ", reason, p); result = jutil_msgnew("normal", user , "Invitation", body); xmlnode_put_attrib(result, "from", jid_full(room->id)); xmlnode_insert_node(result, node); if(room->secret != NULL) { pass = xmlnode_get_tag(result, "x"); xmlnode_insert_cdata(xmlnode_insert_tag(pass, "password"), room->secret, -1); } element = xmlnode_insert_tag(result, "x"); xmlnode_put_attrib(element, "jid", jid_full(room->id)); xmlnode_put_attrib(element, "xmlns", NS_X_CONFERENCE); xmlnode_insert_cdata(element, reason, -1); log_debug(NAME, "[%s] >>>%s<<<", FZONE, xmlnode2str(result)); deliver(dpacket_new(result), NULL); return; }