static struct myentity * chanacs_validate_f(const char *param) { static const struct entity_chanacs_validation_vtable chanacs_ext_validate = { .match_entity = chanacs_ext_match_entity, .match_user = chanacs_ext_match_user, .can_register_channel = chanacs_ext_can_register_channel, .allow_foundership = chanacs_allow_foundership, }; char *name; struct this_exttarget *ext; size_t namelen; if (param == NULL) return NULL; if (*param == '\0') return NULL; // if we already have an object, return it from our tree. if ((ext = mowgli_patricia_retrieve(chanacs_exttarget_tree, param)) != NULL) return entity(ext); ext = mowgli_heap_alloc(chanacs_ext_heap); ext->channel = strshare_get(param); ext->checking = 0; // name the entity... $chanacs:param #define NAMEPREFIX "$chanacs:" namelen = sizeof NAMEPREFIX + strlen(param); name = smalloc(namelen); memcpy(name, NAMEPREFIX, sizeof NAMEPREFIX - 1); memcpy(name + sizeof NAMEPREFIX - 1, param, namelen - sizeof NAMEPREFIX + 1); entity(ext)->name = strshare_get(name); sfree(name); #undef NAMEPREFIX // hook up the entity's validation table. entity(ext)->chanacs_validate = &chanacs_ext_validate; entity(ext)->type = ENT_EXTTARGET; // initialize the object. atheme_object_init(atheme_object(ext), entity(ext)->name, (atheme_object_destructor_fn) chanacs_ext_delete); // add the object to the exttarget tree mowgli_patricia_add(chanacs_exttarget_tree, ext->channel, ext); // return the object as initially unowned by sinking the reference count. return atheme_object_sink_ref(ext); }
static void check_hidehost(user_t *u) { static bool warned = false; char buf[HOSTLEN + 1]; /* do they qualify? */ if (!(u->flags & UF_HIDEHOSTREQ) || u->myuser == NULL || (u->myuser->flags & MU_WAITAUTH)) return; /* don't use this if they have some other kind of vhost */ if (strcmp(u->host, u->vhost)) { slog(LG_DEBUG, "check_hidehost(): +x overruled by other vhost for %s", u->nick); return; } if (me.hidehostsuffix == NULL) { if (!warned) { wallops("Misconfiguration: serverinfo::hidehostsuffix not set"); warned = true; } return; } snprintf(buf, sizeof buf, "%s.%s", entity(u->myuser)->name, me.hidehostsuffix); strshare_unref(u->vhost); u->vhost = strshare_get(buf); slog(LG_DEBUG, "check_hidehost(): %s -> %s", u->nick, u->vhost); }
static myentity_t *chanacs_validate_f(const char *param) { char *name; chanacs_exttarget_t *ext; size_t namelen; if (param == NULL) return NULL; if (*param == '\0') return NULL; /* if we already have an object, return it from our tree. */ if ((ext = mowgli_patricia_retrieve(chanacs_exttarget_tree, param)) != NULL) return entity(ext); ext = mowgli_heap_alloc(chanacs_ext_heap); ext->channel = strshare_get(param); ext->checking = 0; /* name the entity... $chanacs:param */ #define NAMEPREFIX "$chanacs:" namelen = sizeof NAMEPREFIX + strlen(param); name = smalloc(namelen); memcpy(name, NAMEPREFIX, sizeof NAMEPREFIX - 1); memcpy(name + sizeof NAMEPREFIX - 1, param, namelen - sizeof NAMEPREFIX + 1); entity(ext)->name = strshare_get(name); free(name); #undef NAMEPREFIX /* hook up the entity's validation table. */ entity(ext)->chanacs_validate = &chanacs_ext_validate; entity(ext)->type = ENT_EXTTARGET; /* initialize the object. */ object_init(object(ext), entity(ext)->name, (destructor_t) chanacs_ext_delete); /* add the object to the exttarget tree */ mowgli_patricia_add(chanacs_exttarget_tree, ext->channel, ext); /* return the object as initially unowned by sinking the reference count. */ return object_sink_ref(ext); }
/* * user_add(const char *nick, const char *user, const char *host, const char *vhost, const char *ip, * const char *uid, const char *gecos, server_t *server, time_t ts); * * User object factory. * * Inputs: * - nickname of new user * - username of new user * - hostname of new user * - virtual hostname of new user if applicable otherwise NULL * - ip of user if applicable otherwise NULL * - unique identifier (UID) of user if appliable otherwise NULL * - gecos of new user * - pointer to server new user is on * - user's timestamp * * Outputs: * - on success, a new user * - on failure, NULL * * Side Effects: * - if successful, a user is created and added to the users DTree. * - if unsuccessful, a kill has been sent if necessary */ user_t *user_add(const char *nick, const char *user, const char *host, const char *vhost, const char *ip, const char *uid, const char *gecos, server_t *server, time_t ts) { user_t *u, *u2; hook_user_nick_t hdata; slog(LG_DEBUG, "user_add(): %s (%s@%s) -> %s", nick, user, host, server->name); u2 = user_find_named(nick); if (u2 != NULL) { if (server == me.me) { /* caller should not let this happen */ slog(LG_ERROR, "user_add(): tried to add local nick %s which already exists", nick); return NULL; } slog(LG_INFO, "user_add(): nick collision on %s", nick); if (u2->server == me.me) { if (uid != NULL) { /* If the new client has a UID, our * client will have a UID too and the * remote server will send us a kill * if it kills our client. So just kill * their client and continue. */ kill_id_sts(NULL, uid, "Nick collision with services (new)"); return NULL; } if (ts == u2->ts || ((ts < u2->ts) ^ (!irccasecmp(user, u2->user) && !irccasecmp(host, u2->host)))) { /* If the TSes are equal, or if their TS * is less than our TS and the u@h differs, * or if our TS is less than their TS and * the u@h is equal, our client will be * killed. * * Hope that a kill has arrived just before * for our client; we will have reintroduced * it. */ return NULL; } else /* Our client will not be killed. */ return NULL; } else { wallops("Server %s is introducing nick %s which already exists on %s", server->name, nick, u2->server->name); if (uid != NULL && u2->uid != NULL) { kill_id_sts(NULL, uid, "Ghost detected via nick collision (new)"); kill_id_sts(NULL, u2->uid, "Ghost detected via nick collision (old)"); user_delete(u2, "Ghost detected via nick collision (old)"); } else { /* There is no way we can do this properly. */ kill_id_sts(NULL, nick, "Ghost detected via nick collision"); user_delete(u2, "Ghost detected via nick collision"); } return NULL; } } u = mowgli_heap_alloc(user_heap); object_init(object(u), nick, (destructor_t) user_delete); if (uid != NULL) { u->uid = strshare_get(uid); mowgli_patricia_add(uidlist, u->uid, u); } u->nick = strshare_get(nick); u->user = strshare_get(user); u->host = strshare_get(host); u->gecos = strshare_get(gecos); u->chost = strshare_get(vhost ? vhost : host); u->vhost = strshare_get(vhost ? vhost : host); if (ip && strcmp(ip, "0") && strcmp(ip, "0.0.0.0") && strcmp(ip, "255.255.255.255")) u->ip = strshare_get(ip); u->server = server; u->server->users++; mowgli_node_add(u, &u->snode, &u->server->userlist); u->ts = ts ? ts : CURRTIME; mowgli_patricia_add(userlist, u->nick, u); cnt.user++; hdata.u = u; hdata.oldnick = NULL; hook_call_user_add(&hdata); return hdata.u; }
static void m_mode(sourceinfo_t *si, int parc, char *parv[]) { user_t *u; char *p; if (*parv[0] == '#') channel_mode(NULL, channel_find(parv[0]), parc - 1, &parv[1]); else { /* Yes this is a nick and not a UID -- jilles */ u = user_find_named(parv[0]); if (u == NULL) { slog(LG_DEBUG, "m_mode(): user mode for unknown user %s", parv[0]); return; } user_mode(u, parv[1]); if (strchr(parv[1], 'x')) { u->flags |= UF_HIDEHOSTREQ; check_hidehost(u); } if (strchr(parv[1], 'h')) { if (parc > 2) { /* assume +h */ p = strchr(parv[2], '@'); if (p == NULL) { strshare_unref(u->vhost); u->vhost = strshare_get(parv[2]); } else { char userbuf[USERLEN]; strshare_unref(u->vhost); u->vhost = strshare_get(p + 1); mowgli_strlcpy(userbuf, parv[2], sizeof userbuf); p = strchr(userbuf, '@'); if (p != NULL) *p = '\0'; strshare_unref(u->user); u->user = strshare_get(userbuf); } slog(LG_DEBUG, "m_mode(): user %s setting vhost %s@%s", u->nick, u->user, u->vhost); } else { /* must be -h */ /* XXX we don't know the original ident */ slog(LG_DEBUG, "m_mode(): user %s turning off vhost", u->nick); strshare_unref(u->vhost); u->vhost = strshare_get(u->host); /* revert to +x vhost if applicable */ check_hidehost(u); } } } }
static void m_nick(sourceinfo_t *si, int parc, char *parv[]) { user_t *u; char ipstring[HOSTIPLEN]; char *p; int i; /* got the right number of args for an introduction? */ if (parc >= 8) { /* -> AB N jilles 1 1137687480 jilles jaguar.test +oiwgrx jilles B]AAAB ABAAE :Jilles Tjoelker */ /* -> AB N test4 1 1137690148 jilles jaguar.test +iw B]AAAB ABAAG :Jilles Tjoelker */ slog(LG_DEBUG, "m_nick(): new user on `%s': %s", si->s->name, parv[0]); decode_p10_ip(parv[parc - 3], ipstring); u = user_add(parv[0], parv[3], parv[4], NULL, ipstring, parv[parc - 2], parv[parc - 1], si->s, atoi(parv[2])); if (u == NULL) return; if (parv[5][0] == '+') { user_mode(u, parv[5]); i = 1; if (strchr(parv[5], 'r')) { p = strchr(parv[5+i], ':'); if (p != NULL) *p++ = '\0'; handle_burstlogin(u, parv[5+i], p ? atol(p) : 0); /* killed to force logout? */ if (user_find(parv[parc - 2]) == NULL) return; i++; } if (strchr(parv[5], 'h')) { p = strchr(parv[5+i], '@'); if (p == NULL) { strshare_unref(u->vhost); u->vhost = strshare_get(parv[5 + i]); } else { char userbuf[USERLEN]; strshare_unref(u->vhost); u->vhost = strshare_get(p + 1); mowgli_strlcpy(userbuf, parv[5+i], sizeof userbuf); p = strchr(userbuf, '@'); if (p != NULL) *p = '\0'; strshare_unref(u->user); u->user = strshare_get(userbuf); } i++; } if (strchr(parv[5], 'x')) { u->flags |= UF_HIDEHOSTREQ; /* this must be after setting the account name */ check_hidehost(u); } } handle_nickchange(u); } /* if it's only 2 then it's a nickname change */ else if (parc == 2) { if (!si->su) { slog(LG_DEBUG, "m_nick(): server trying to change nick: %s", si->s != NULL ? si->s->name : "<none>"); return; } slog(LG_DEBUG, "m_nick(): nickname change from `%s': %s", si->su->nick, parv[0]); if (user_changenick(si->su, parv[0], atoi(parv[1]))) return; handle_nickchange(si->su); } else { slog(LG_DEBUG, "m_nick(): got NICK with wrong (%d) number of params", parc); for (i = 0; i < parc; i++) slog(LG_DEBUG, "m_nick(): parv[%d] = %s", i, parv[i]); } }