int jlimit_check(jlimit r, char *key, int points) { int now = time(NULL); if (r == NULL) return 0; /* make sure we didn't go over the time frame or get a null/new key */ if ((now - r->start) > r->maxt || key == NULL || j_strcmp(key, r->key) != 0) { /* start a new key */ free(r->key); if (key != NULL) /* We use strdup instead of pstrdup since r->key needs to be free'd before and more often than the rest of the rlimit structure */ r->key = strdup(key); else r->key = NULL; r->start = now; r->points = 0; } r->points += points; /* if we're within the time frame and over the point limit */ if (r->points > r->maxp && (now - r->start) < r->maxt) { return 1; /* we don't reset the rate here, so that it remains rated until the time runs out */ } return 0; }
result mt_ns_rem(mpacket mp, void *arg) { if (j_strcmp(mt_packet_data(mp,0),"REM") == 0 && j_strcmp(mt_packet_data(mp,2),"RL") == 0) { session s = (session) arg; char *user = mt_packet_data(mp,4); if (user != NULL) { muser u = mt_user(s,user); u->list ^= LIST_RL; mt_user_unsubscribe(s,u); return r_DONE; } } return r_ERR; }
static dps_param_t handle_get_file_id(dps_appctx_t appctx, ptp_obj_handle_t autprint_mrk_file_id, char *dcf_file_path, ptp_obj_handle_t *id) { jint_t i; char *filename = NULL; dps_param_t rc; DECLARE_FNAME("handle_get_file_id"); DBG_X(DSLAVE_DPS_API, ("%s: entered\n", fname)); *id = 0; rc = DPS_PARAM_MAKE(DPS_RESULT_UNSUPPORTED_OP, DPS_RESULT_MIN_INVALID_VALUE); for (i=0; sample_image[i].image; i++) { if (!sample_image[i].name) continue; filename = j_strdup(sample_image[i].name); if (!filename) { DBG_E(DSLAVE_DPS_API, ("%s: error allocating memory (strdup)\n", fname)); rc = DPS_RESULT_UNEXECUTED_OP; goto Exit; } to_upper(filename); /* TODO: The code that should be implemented here is not a * straightforward string comparison. * The dcf_file_path is the image's path relative * to the DPOF file. In a real system e.g, the image'ss full path * would be reconstructed in order to do a full path search * for the file */ if (!j_strcmp(dcf_file_path+sizeof(DCF_PREFIX)-1, filename)) { jfree(filename); break; } jfree(filename); } if (sample_image[i].image) { *id = sample_image[0].id; rc = DPS_RESULT_OK; } DBG_X(DSLAVE_DPS_API, ("%s: autprint_id: 0x%X filename: %s" " img_id: 0x%X\n", fname, autprint_mrk_file_id, dcf_file_path, *id)); Exit: return rc; }
/* loop through both a and b comparing everything, attribs, cdata, children, etc */ int xmlnode_cmp(xmlnode a, xmlnode b) { int ret = 0; while(1) { if(a == NULL && b == NULL) return 0; if(a == NULL || b == NULL) return -1; if(xmlnode_get_type(a) != xmlnode_get_type(b)) return -1; switch(xmlnode_get_type(a)) { case NTYPE_ATTRIB: ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); if(ret != 0) return -1; ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); if(ret != 0) return -1; break; case NTYPE_TAG: ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); if(ret != 0) return -1; ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); if(ret != 0) return -1; ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); if(ret != 0) return -1; break; case NTYPE_CDATA: ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); if(ret != 0) return -1; } a = xmlnode_get_nextsibling(a); b = xmlnode_get_nextsibling(b); } }
char *jutil_regkey(char *key, char *seed) { static char keydb[KEYBUF][41]; static char seeddb[KEYBUF][41]; static int last = -1; char *str, strint[32]; int i; /* blanket the keydb first time */ if(last == -1) { last = 0; memset(&keydb,0,KEYBUF*41); memset(&seeddb,0,KEYBUF*41); srand(time(NULL)); } /* creation phase */ if(key == NULL && seed != NULL) { /* create a random key hash and store it */ sprintf(strint,"%d",rand()); strcpy(keydb[last],shahash(strint)); /* store a hash for the seed associated w/ this key */ strcpy(seeddb[last],shahash(seed)); /* return it all */ str = keydb[last]; last++; if(last == KEYBUF) last = 0; return str; } /* validation phase */ str = shahash(seed); for(i=0;i<KEYBUF;i++) if(j_strcmp(keydb[i],key) == 0 && j_strcmp(seeddb[i],str) == 0) { seeddb[i][0] = '\0'; /* invalidate this key */ return keydb[i]; } return NULL; }
xhn _xhash_node_get(xht h, const char *key, int index) { xhn n; int i = index % h->prime; for(n = &h->zen[i]; n != NULL; n = n->next) if(j_strcmp(key, n->key) == 0) return n; return NULL; }
void mt_unknown_process(mti ti, jpacket jp) { switch (jp->type) { case JPACKET_IQ: if (jp->to->user != NULL || (ti->con && j_strcmp(ti->con_id,jp->to->server) == 0)) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_unknown_bounce,(void *) jp); } else { if (j_strcmp(jp->iqns,NS_REGISTER) == 0) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_reg_unknown,(void *) jp); } else mt_iq_server(ti,jp); } break; case JPACKET_MESSAGE: case JPACKET_S10N: /* message and s10n aren't allowed without a valid session */ if (jp->to->user != NULL || jpacket_subtype(jp) != JPACKET__SUBSCRIBED) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_unknown_bounce,(void *) jp); break; } /* fall through here to free the node */ case JPACKET_PRESENCE: if (jpacket_subtype(jp) == JPACKET__AVAILABLE && jp->to->user == NULL) { jp->aux1 = (void *) ti; mtq_send(NULL,jp->p,&mt_presence_unknown,(void *) jp); break; } xmlnode_free(jp->x); } }
result mt_ns_cvr(mpacket mp, void *arg) { session s = (session) arg; if (j_strcmp(mt_packet_data(mp,0),"CVR") == 0) { mt_stream_register(s->st,&mt_ns_usr_I,(void *) s); mt_cmd_usr_I(s->st,s->user); return r_DONE; } return r_ERR; }
/* child that cleans up a session session thread */ void _js_session_end(session s) { xmlnode x, temp; /* debug message */ log_debug("THREAD:SESSION exiting"); /* only for moules es_END */ temp = s->presence; if (temp != NULL && j_strcmp(xmlnode_get_attrib(temp, "type"), "unavailable") != 0) { /* create a new presence packet with the reason the user is unavailable */ x = jutil_presnew(JPACKET__UNAVAILABLE, NULL, NULL); xmlnode_put_attrib(x, "from", jid_full(s->id)); /* free the old presence packet */ s->presence = x; } else { temp = NULL; } /* make sure the service knows the session is gone */ if (s->sid != NULL) js_session_route(s, NULL); /* let the modules have their heyday */ js_mapi_call(NULL, es_END, NULL, s->u, s); /* let the user struct go */ THREAD_DEC(s->u->ref); /* free old presence */ if (temp) xmlnode_free(temp); /* free the session's presence state */ temp = s->presence; s->presence = NULL; s->q->count--; /* free the session's memory pool */ register_beat(60, js_session_free, s); /* free unavailable presence we have set */ if (temp) xmlnode_free(temp); }
static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) { xmlnode current; /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with the specified name */ current = firstsibling; while (current != NULL) { if ((current->type == type) && (j_strcmp(current->name, name) == 0)) return current; else current = current->next; } return NULL; }
result xdb_results(instance id, dpacket p, void *arg) { xdbcache xc = (xdbcache) arg; xdbrequest_p cur, last; unsigned int idnum; char *idstr; if (p->type != p_NORM || *(xmlnode_get_name(p->x)) != 'x') return r_PASS; /* yes, we are matching ANY <x*> element */ log_debug("xdb_results checking xdb packet %s", xmlnode2str(p->x)); if ((idstr = xmlnode_get_attrib(p->x, "id")) == NULL) return r_ERR; idnum = atoi(idstr); SEM_LOCK(xc->sem); for (last = NULL, cur = xc->first; (cur) && (cur->id != idnum); last = cur, cur = cur->next); if (!cur) { pool_free(p->p); SEM_UNLOCK(xc->sem); return r_DONE; } /* associte only a non-error packet w/ waiting cache */ if (j_strcmp(xmlnode_get_attrib(p->x, "type"), "error") == 0) { cur->data = NULL; pool_free(p->p); } else cur->data = p->x; if (!last) xc->first = cur->next; else last->next = cur->next; cur->external = 0; SEM_UNLOCK(xc->sem); cur->preblock = 1; return r_DONE; }
result dnsrv_deliver(instance i, dpacket p, void* args) { dns_io di = (dns_io)args; xmlnode c; int timeout = di->cache_timeout; char *ip; jid to; /* if we get a route packet, it has to be to *us* and have the child as the real packet */ if(p->type == p_ROUTE) { if(j_strcmp(p->host,i->id) != 0 || (to = jid_new(p->p,xmlnode_get_attrib(xmlnode_get_firstchild(p->x),"to"))) == NULL) return r_ERR; p->x=xmlnode_get_firstchild(p->x); p->id = to; p->host = to->server; } /* Ensure this packet doesn't already have an IP */ if(xmlnode_get_attrib(p->x, "ip") || xmlnode_get_attrib(p->x, "iperror")) { log_notice(p->host, "dropping looping dns lookup request: %s", xmlnode2str(p->x)); xmlnode_free(p->x); return r_DONE; } /* try the cache first */ if((c = xhash_get(di->cache_table, p->host)) != NULL) { /* if there's no IP, cached failed lookup, time those out 10 times faster! (weird, I know, *shrug*) */ if((ip = xmlnode_get_attrib(c,"ip")) == NULL) timeout = timeout / 10; if((time(NULL) - (int)xmlnode_get_vattrib(c,"t")) > timeout) { /* timed out of the cache, lookup again */ xmlnode_free(c); xhash_zap(di->cache_table,p->host); }else{ /* yay, send back right from the cache */ dnsrv_resend(p->x, ip, xmlnode_get_attrib(c,"to")); return r_DONE; } } dnsrv_lookup(di, p); return r_DONE; }
result xdb_results(instance id, dpacket p, void *arg) { xdbcache xc = (xdbcache)arg; xdbcache curx; int idnum; char *idstr; if(p->type != p_NORM || *(xmlnode_get_name(p->x)) != 'x') return r_PASS; /* yes, we are matching ANY <x*> element */ log_debug(ZONE,"xdb_results checking xdb packet %s",xmlnode2str(p->x)); if((idstr = xmlnode_get_attrib(p->x,"id")) == NULL) return r_ERR; idnum = atoi(idstr); pthread_mutex_lock(&(xc->sem)); for(curx = xc->next; curx->id != idnum && curx != xc; curx = curx->next); /* spin till we are where we started or find our id# */ /* we got an id we didn't have cached, could be a dup, ignore and move on */ if(curx->id != idnum) { pool_free(p->p); pthread_mutex_unlock(&(xc->sem)); return r_DONE; } /* associte only a non-error packet w/ waiting cache */ if(j_strcmp(xmlnode_get_attrib(p->x,"type"),"error") == 0) { curx->data = NULL; pool_free(p->p); // very bad memory leak } else curx->data = p->x; /* remove from ring */ curx->prev->next = curx->next; curx->next->prev = curx->prev; pthread_mutex_unlock(&(xc->sem)); /* free the thread! */ curx->preblock = 1; return r_DONE; /* we processed it */ }
mreturn mod_agents_handler(mapi m, void *arg) { if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (jpacket_subtype(m->packet) != JPACKET__GET) return M_PASS; if (m->s != NULL && (m->packet->to != NULL && j_strcmp(jid_full(m->packet->to), m->packet->from->server) != 0)) return M_PASS; /* for session calls, only answer to=NULL or to=server */ if (NSCHECK(m->packet->iq, NS_AGENT)) return mod_agents_agent(m); if (NSCHECK(m->packet->iq, NS_AGENTS)) return mod_agents_agents(m); return M_PASS; }
void mt_ns_xfr(mpacket mp, session s) { if (j_strcmp(mt_packet_data(mp,2),"NS") == 0) { char *host = mt_packet_data(mp,3); char *port = strchr(host,':'); if (port != NULL) { *port = '\0'; ++port; } mt_ns_close(s); mt_ns_connect(s,host,j_atoi(port,1863)); } else { log_debug(ZONE,"Session[%s], NS XFR Error, %s",jid_full(s->id),mt_packet_data(mp,2)); } }
result mt_ns_ver(mpacket mp, void *arg) { session s = (session) arg; char *cmd = mt_packet_data(mp,0); if (j_strcmp(cmd,"VER") == 0) { mt_stream_register(s->st,&mt_ns_cvr,(void *) s); mt_cmd_cvr(s->st, s->user); } else if (j_atoi(cmd,0) != 0) { /* The server is probably down */ log_debug(ZONE,"Session[%s], Error code %s, retrying",jid_full(s->id),cmd); mt_ns_close(s); mt_ns_reconnect(s); } else return r_ERR; return r_DONE; }
/* we should be last in the list of modules */ JSM_FUNC void mod_log(jsmi si) { xmlnode cfg = js_config(si, "archive"); jid svcs = NULL; log_debug("mod_log init"); /* look for archiving service too */ for (cfg = xmlnode_get_firstchild(cfg); cfg != NULL; cfg = xmlnode_get_nextsibling(cfg)) { if (xmlnode_get_type(cfg) != NTYPE_TAG || j_strcmp(xmlnode_get_name(cfg), "service") != 0) continue; if (svcs == NULL) svcs = jid_new(si->p, xmlnode_get_data(cfg)); else jid_append(svcs, jid_new(si->p, xmlnode_get_data(cfg))); } js_mapi_register(si, e_SESSION, mod_log_session, (void *) svcs); }
/* 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; }
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); } }
int xdbsql_roomoutcast_set(XdbSqlDatas * self, const char *room, xmlnode data) { xmlnode query; /* the query for this function */ xmlnode x, x2; /* used to iterate through the rules */ query_def qd; /* the query definition */ XdbSqlResult *result; /* return from query */ char *data_userid = NULL; char *data_reason = NULL; char *data_responsibleid = NULL; char *data_responsiblenick = NULL; const char *querystring; char *name; if (!room) { /* the room was not specified - we have to bug off */ log_error(NULL, "[xdbsql_roomoutcast_set] room not specified"); return 0; } if (!data) { return roomoutcast_purge(self, room); } /* Get the query definition. */ query = xdbsql_query_get(self, "roomoutcast-set"); if (!query) { log_error(NULL, "--!!-- WTF? roomoutcast-set query not found?"); return 0; } /* Purge any existing roomconfig data. */ roomoutcast_purge(self, room); for (x = xmlnode_get_firstchild(data); x; x = xmlnode_get_nextsibling(x)) { qd = xdbsql_querydef_init(self, query); xdbsql_querydef_setvar(qd, "room", room); data_userid = data_reason = data_responsibleid = data_responsiblenick = NULL; name = xmlnode_get_name(x); if (j_strcmp(name, "item") == 0) { data_userid = xmlnode_get_attrib(x, "jid"); for (x2 = xmlnode_get_firstchild(x); x2; x2 = xmlnode_get_nextsibling(x2)) { name = xmlnode_get_name(x2); if (j_strcmp(name, "reason") == 0) { data_responsibleid = xmlnode_get_attrib(x2, "actor"); data_responsiblenick = xmlnode_get_attrib(x2, "nick"); data_reason = GET_CHILD_DATA(x2); } } } if (data_userid && *data_userid) xdbsql_querydef_setvar(qd, "userid", data_userid); if (data_reason && *data_reason) xdbsql_querydef_setvar(qd, "reason", data_reason); if (data_responsibleid && *data_responsibleid) xdbsql_querydef_setvar(qd, "responsibleid", data_responsibleid); if (data_responsiblenick && *data_responsiblenick) xdbsql_querydef_setvar(qd, "responsiblenick", data_responsiblenick); querystring = xdbsql_querydef_finalize(qd); result = sqldb_query(self, querystring); xdbsql_querydef_free(qd); if (!result) log_error(NULL, "[xdbsql_roomoutcast_set] query failed : %s", sqldb_error(self)); else sqldb_free_result(result); } return 1; }
/* * 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; }
mreturn mod_stats_server(mapi m, void *arg) { xmlnode cur; int i; if (m->packet->type != JPACKET_IQ) return M_IGNORE; if (jpacket_subtype(m->packet) != JPACKET__GET) return M_PASS; if (!NSCHECK(m->packet->iq, NS_STATS)) return M_PASS; if (m->packet->to->resource) return M_PASS; /* get data from the config file */ i = 0; if (xmlnode_get_tag(js_config(m->si, "stats"), "allow_all") != NULL) i = 1; log_debug("handling stats get %s", jid_full(m->packet->from)); /* check if admin */ if ((i == 0) && (!js_admin_jid(m->si, jid_user(m->packet->from), ADMIN_READ))) { jutil_error(m->packet->x, TERROR_AUTH); jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; } /* check if any stat have given iq query */ cur = xmlnode_get_firstchild(m->packet->iq); for (; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if (xmlnode_get_type(cur) != NTYPE_TAG) continue; break; } if (cur != NULL) cur = xmlnode_get_firstchild(m->packet->iq); jutil_tofrom(m->packet->x); xmlnode_put_attrib(m->packet->x, "type", "result"); /* return available stats */ if (!cur) { for (i = 0; available_stats[i]; i++) { xmlnode_put_attrib(xmlnode_insert_tag (m->packet->iq, "stat"), "name", available_stats[i]); } jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; } /* return server stats */ /* cur is already first stat */ for (; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { char *name; char buf[31]; int found; if (xmlnode_get_type(cur) != NTYPE_TAG) continue; if (j_strcmp(xmlnode_get_name(cur), "stat") != 0) continue; name = xmlnode_get_attrib(cur, "name"); if (!name) continue; log_debug("get stats for %s", name); found = 0; for (i = 0; available_stats[i]; i++) { if (j_strcmp(available_stats[i], name) != 0) continue; log_debug("stats for %s", name); /* give stats */ found = 1; /* time/uptime */ if (j_strcmp(name, "time/uptime") == 0) { snprintf(buf, 30, "%d", time(NULL) - m->si->stats->started); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "seconds"); } /* users/online */ if (j_strcmp(name, "users/online") == 0) { snprintf(buf, 30, "%d", m->si->stats->sessioncount); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/max_online_today") == 0) { snprintf(buf, 30, "%d", m->si->stats->session_max_today); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/max_online_yesterday") == 0) { snprintf(buf, 30, "%d", m->si->stats-> session_max_yesterday); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/registered_today") == 0) { snprintf(buf, 30, "%d", m->si->stats-> users_registered_today); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "users/registered_from_start") == 0) { snprintf(buf, 30, "%d", m->si->stats-> users_registered_from_start); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "users"); } if (j_strcmp(name, "bandwidth/packets-in") == 0) { snprintf(buf, 30, "%lu", m->si->stats->packets_in); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "packets"); } if (j_strcmp(name, "bandwidth/packets-out") == 0) { snprintf(buf, 30, "%lu", m->si->stats->packets_out); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "packets"); } #ifndef WIN32 if (j_strcmp(name, "memory/usage") == 0) { long mem = get_memory_usage(); if (mem > 0) { snprintf(buf, 30, "%lu", mem); xmlnode_put_attrib(cur, "value", buf); xmlnode_put_attrib(cur, "units", "bytes"); } else found = 0; } #endif break; } if (found <= 0) { xmlnode err; err = xmlnode_insert_tag(cur, "error"); xmlnode_put_attrib(err, "code", "404"); xmlnode_insert_cdata(err, "Not Found", -1); } } jpacket_reset(m->packet); js_deliver(m->si, m->packet); return M_HANDLED; }
/* 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; }
/** 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; }
/** * caching wrapper around a stringprep function * * @param in_out_buffer buffer containing what has to be stringpreped and that gets the result * @param max_len size of the buffer * @param cache the used cache, defining also the used stringprep profile * @return the return code of the stringprep call */ static int _jid_cached_stringprep(char *in_out_buffer, int max_len, _jid_prep_cache_t cache) { _jid_prep_entry_t preped; int result = STRINGPREP_OK; /* check that the cache already exists * we can not do anything as we don't know which profile has to be used */ if (cache == NULL) { return STRINGPREP_UNKNOWN_PROFILE; } /* is there something that has to be stringpreped? */ if (in_out_buffer == NULL) { return STRINGPREP_OK; } /* acquire the lock on the cache */ g_mutex_lock(cache->mutex); /* check if the requested preparation has already been done */ preped = (_jid_prep_entry_t)g_hash_table_lookup(cache->hashtable, in_out_buffer); if (preped != NULL) { /* we already prepared this argument */ if (preped->size <= max_len) { /* we can use the result */ /* update the statistic */ preped->used_count++; preped->last_used = time(NULL); /* do we need to copy the result? */ if (preped->preped != NULL) { /* copy the result */ strcpy(in_out_buffer, preped->preped); } result = STRINGPREP_OK; } else { /* we need a bigger buffer */ result = STRINGPREP_TOO_SMALL_BUFFER; } /* we're done, release the lock on the cache */ g_mutex_unlock(cache->mutex); } else { char *original; /* stringprep needs time, release the lock on the cache for the meantime */ g_mutex_unlock(cache->mutex); /* we have to keep the key */ original = strdup(in_out_buffer); /* try to prepare the string */ result = stringprep(in_out_buffer, max_len, STRINGPREP_NO_UNASSIGNED, cache->profile); /* did we manage to prepare the string? */ if (result == STRINGPREP_OK && original != NULL) { /* generate an entry for the cache */ preped = (_jid_prep_entry_t)malloc(sizeof(struct _jid_prep_entry_st)); if (preped != NULL) { /* has there been modified something? */ if (j_strcmp(in_out_buffer, original) == 0) { /* no, we don't need to store a copy of the original string */ preped->preped = NULL; } else { /* yes, store the stringpreped string */ preped->preped = strdup(in_out_buffer); } preped->last_used = time(NULL); preped->used_count = 1; preped->size = strlen(in_out_buffer)+1; /* acquire the lock on the cache again */ g_mutex_lock(cache->mutex); /* store the entry in the cache */ g_hash_table_insert(cache->hashtable, original, preped); /* we're done, release the lock on the cache */ g_mutex_unlock(cache->mutex); } else { /* we don't need the copy of the key, if there is no memory to store it */ free(original); } } else { /* we don't need the copy of the original value */ if (original != NULL) free(original); } } return result; }
mreturn mod_agents_agents(mapi m) { xmlnode ret, retq, agents, cur, a, cur2; /* get data from the config file */ agents = js_config(m->si, "browse"); /* if we don't have anything to say, bounce */ if (agents == NULL) return M_PASS; log_debug("handling agents query"); /* build the result IQ */ ret = jutil_iqresult(m->packet->x); retq = xmlnode_insert_tag(ret, "query"); xmlnode_put_attrib(retq, "xmlns", NS_AGENTS); /* parse the new browse data into old agents format */ for (cur = xmlnode_get_firstchild(agents); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if (xmlnode_get_type(cur) != NTYPE_TAG) continue; /* generic <agent> part */ a = xmlnode_insert_tag(retq, "agent"); xmlnode_put_attrib(a, "jid", xmlnode_get_attrib(cur, "jid")); xmlnode_insert_cdata(xmlnode_insert_tag(a, "name"), xmlnode_get_attrib(cur, "name"), -1); xmlnode_insert_cdata(xmlnode_insert_tag(a, "service"), xmlnode_get_attrib(cur, "type"), -1); if (j_strcmp(xmlnode_get_name(cur), "conference") == 0) xmlnode_insert_tag(a, "groupchat"); /* map the included <ns>'s in browse to the old agent flags */ for (cur2 = xmlnode_get_firstchild(cur); cur2 != NULL; cur2 = xmlnode_get_nextsibling(cur2)) { if (j_strcmp(xmlnode_get_name(cur2), "ns") != 0) continue; if (j_strcmp (xmlnode_get_data(cur2), "jabber:iq:register") == 0) xmlnode_insert_tag(a, "register"); if (j_strcmp (xmlnode_get_data(cur2), "jabber:iq:search") == 0) xmlnode_insert_tag(a, "search"); if (j_strcmp (xmlnode_get_data(cur2), "jabber:iq:gateway") == 0) xmlnode_insert_cdata(xmlnode_insert_tag (a, "transport"), "Enter ID", -1); } } jpacket_reset(m->packet); if (m->s != NULL) { /* XXX null session hack! */ xmlnode_put_attrib(m->packet->x, "from", m->packet->from->server); js_session_to(m->s, m->packet); } else { js_deliver(m->si, m->packet); } return M_HANDLED; }
result mt_ns_packets(mpacket mp, void *arg) { session s = (session) arg; if (mp == NULL) { s->connected = 0; s->friendly_flag = 1; s->st = NULL; mt_ns_end_sbs(s); if (s->exit_flag == 0) { log_debug(ZONE,"Session[%s], MSN server connection closed",jid_full(s->id)); mt_ns_reconnect(s); } SREF_DEC(s); } else if (s->exit_flag == 0) { char *cmd = mt_packet_data(mp,0); if (j_strcmp(cmd,"NLN") == 0) mt_ns_nln(mp,s); else if (j_strcmp(cmd,"FLN") == 0) mt_ns_fln(mp,s); else if (j_strcmp(cmd,"ADD") == 0) mt_ns_add(mp,arg); else if (j_strcmp(cmd,"REM") == 0) mt_ns_rem(mp,arg); else if (j_strcmp(cmd,"RNG") == 0) mt_ns_rng(mp,s); else if (j_strcmp(cmd,"XFR") == 0) mt_ns_xfr(mp,s); else if (j_strcmp(cmd,"MSG") == 0) mt_ns_msg(mp,s); else if (j_strcmp(cmd,"NOT") == 0) mt_ns_not(mp,s); else if (j_strcmp(cmd,"ILN") == 0) mt_ns_iln(mp,s); else if (j_strcmp(cmd,"LST") == 0) mt_user_syn(mp,s); else if (j_strcmp(cmd,"CHL") == 0) mt_ns_chl(mp,s); else if (j_strcmp(cmd,"QRY") == 0) ; // This can be safely ignored, it's just a response to our challenge response (in the form QRY msg_id) else if (j_strcmp(cmd,"PRP") == 0) ; // To do with phone numbers - ignore else if (j_strcmp(cmd,"BRP") == 0) ; // To do with phone numbers - ignore else if (j_strcmp(cmd,"LSG") == 0) ; // To do with groups on the MSN server, we have no way of using this info, ignore else if (j_strcmp(cmd,"GTC") == 0) ; // To do with privacy settings - ignore else if (j_strcmp(cmd,"BLP") == 0) ; // To do with privacy settings - ignore else if (j_strcmp(cmd,"OUT") == 0) { s->connected = 0; s->friendly_flag = 1; if (j_strcmp(mt_packet_data(mp,1),"OTH") == 0) mt_session_kill(s,(terror){409,"Session was replaced"}); else mt_session_kill(s,TERROR_EXTERNAL); } else if (j_strcmp(cmd,"REA") && j_strcmp(cmd,"CHG")) return r_ERR; } return r_DONE; }
/* * xmlnode_get_tag -- find given tag in an xmlnode tree * * parameters * parent -- pointer to the parent tag * name -- "name" for the child tag of that name * "name/name" for a sub child (recurses) * "?attrib" to match the first tag with that attrib defined * "?attrib=value" to match the first tag with that attrib and value * "=cdata" to match the cdata contents of the child * or any combination: "name/name/?attrib", "name=cdata", etc * * results * a pointer to the tag matching search criteria * or NULL if search was unsuccessfull */ xmlnode xmlnode_get_tag(xmlnode parent, const char* name) { char *str, *slash, *qmark, *equals; xmlnode step, ret; if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); str = strdup(name); slash = strstr(str, "/"); qmark = strstr(str, "?"); equals = strstr(str, "="); if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) { /* of type =cdata */ *equals = '\0'; equals++; for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) { if(xmlnode_get_type(step) != NTYPE_TAG) continue; if(*str != '\0') if(j_strcmp(xmlnode_get_name(step),str) != 0) continue; if(j_strcmp(xmlnode_get_data(step),equals) != 0) continue; break; } free(str); return step; } if(qmark != NULL && (slash == NULL || qmark < slash)) { /* of type ?attrib */ *qmark = '\0'; qmark++; if(equals != NULL) { *equals = '\0'; equals++; } for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) { if(xmlnode_get_type(step) != NTYPE_TAG) continue; if(*str != '\0') if(j_strcmp(xmlnode_get_name(step),str) != 0) continue; if(xmlnode_get_attrib(step,qmark) == NULL) continue; if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) continue; break; } free(str); return step; } *slash = '\0'; ++slash; for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) { if(xmlnode_get_type(step) != NTYPE_TAG) continue; if(j_strcmp(xmlnode_get_name(step),str) != 0) continue; ret = xmlnode_get_tag(step, slash); if(ret != NULL) { free(str); return ret; } } free(str); return NULL; }
void dnsrv(instance i, xmlnode x) { xdbcache xc = NULL; xmlnode config = NULL; xmlnode iternode = NULL; dns_resend_list tmplist = NULL; /* Setup a struct to hold dns_io handles */ dns_io di; di = pmalloco(i->p, sizeof(_dns_io)); di->mempool = i->p; /* Load config from xdb */ xc = xdb_cache(i); config = xdb_get(xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:dnsrv"); /* Build a list of services/resend hosts */ iternode = xmlnode_get_lastchild(config); while (iternode != NULL) { if (j_strcmp("resend", xmlnode_get_name(iternode)) != 0) { iternode = xmlnode_get_prevsibling(iternode); continue; } /* Allocate a new list node */ tmplist = pmalloco(di->mempool, sizeof(_dns_resend_list)); tmplist->service = pstrdup(di->mempool, xmlnode_get_attrib(iternode, "service")); tmplist->host = pstrdup(di->mempool, xmlnode_get_data(iternode)); /* Insert this node into the list */ tmplist->next = di->svclist; di->svclist = tmplist; /* Move to next child */ iternode = xmlnode_get_prevsibling(iternode); } log_debug(ZONE, "dnsrv debug: %s\n", xmlnode2str(config)); /* Setup the hash of dns_packet_list */ di->packet_table = xhash_new(j_atoi(xmlnode_get_attrib(config,"queuemax"),101)); di->packet_timeout = j_atoi(xmlnode_get_attrib(config,"queuetimeout"),60); register_beat(di->packet_timeout, dnsrv_beat_packets, (void *)di); /* Setup the internal hostname cache */ di->cache_table = xhash_new(j_atoi(xmlnode_get_attrib(config,"cachemax"),1999)); di->cache_timeout = j_atoi(xmlnode_get_attrib(config,"cachetimeout"),3600); /* 1 hour dns cache? XXX would be nice to get the right value from dns! */ xmlnode_free(config); /* spawn a thread that get's forked, and wait for it since it sets up the fd's */ pth_join(pth_spawn(PTH_ATTR_DEFAULT,(void*)dnsrv_thread,(void*)di),NULL); if(di->pid < 0) { log_error(i->id,"dnsrv failed to start, unable to fork and/or create pipes"); return; } /* Start IO thread */ pth_spawn(PTH_ATTR_DEFAULT, dnsrv_process_io, di); /* Register an incoming packet handler */ register_phandler(i, o_DELIVER, dnsrv_deliver, (void*)di); /* register a cleanup function */ pool_cleanup(i->p, dnsrv_shutdown, (void*)di); }
int jpacket_subtype(jpacket p) { char *type; int ret = p->subtype; if(ret != JPACKET__UNKNOWN) return ret; ret = JPACKET__NONE; /* default, when no type attrib is specified */ type = xmlnode_get_attrib(p->x, "type"); if(j_strcmp(type,"error") == 0) ret = JPACKET__ERROR; else switch(p->type) { case JPACKET_MESSAGE: if(j_strcmp(type,"chat") == 0) ret = JPACKET__CHAT; else if(j_strcmp(type,"groupchat") == 0) ret = JPACKET__GROUPCHAT; else if(j_strcmp(type,"headline") == 0) ret = JPACKET__HEADLINE; break; case JPACKET_S10N: if(j_strcmp(type,"subscribe") == 0) ret = JPACKET__SUBSCRIBE; else if(j_strcmp(type,"subscribed") == 0) ret = JPACKET__SUBSCRIBED; else if(j_strcmp(type,"unsubscribe") == 0) ret = JPACKET__UNSUBSCRIBE; else if(j_strcmp(type,"unsubscribed") == 0) ret = JPACKET__UNSUBSCRIBED; break; case JPACKET_IQ: if(j_strcmp(type,"get") == 0) ret = JPACKET__GET; else if(j_strcmp(type,"set") == 0) ret = JPACKET__SET; else if(j_strcmp(type,"result") == 0) ret = JPACKET__RESULT; break; } p->subtype = ret; return ret; }