Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
/*
 * 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;
}
Example #5
0
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);
            }
        }
    }
}
Example #6
0
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]);
    }
}