Пример #1
0
static int
m_ison(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	char *nick;
	char *p;
	char buf[IRCD_BUFSIZE];
	int i;

	memset(buf, 0, sizeof(buf));

	for(i = 1; i < parc; i++)
	{
		char *cs = LOCAL_COPY(parv[i]);
		for(nick = rb_strtok_r(cs, " ", &p); nick; nick = rb_strtok_r(NULL, " ", &p))
		{
			target_p = find_named_client(nick);

			if(target_p != NULL)
			{
				rb_strlcat(buf, target_p->name, sizeof(buf));
				rb_strlcat(buf, " ", sizeof(buf));
			}
		}
	}
	sendto_one_numeric(source_p, s_RPL(RPL_ISON), buf);
	return 0;

}
Пример #2
0
/*
 * m_ison added by Darren Reed 13/8/91 to act as an efficent user indicator
 * with respect to cpu/bandwidth used. Implemented for NOTIFY feature in
 * clients. Designed to reduce number of whois requests. Can process
 * nicknames in batches as long as the maximum buffer length.
 *
 * format:
 * ISON :nicklist
 */
static int
m_ison(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	char *nick;
	char *p;
	char *current_insert_point, *current_insert_point2;
	int len;
	int i;
	int done = 0;

	current_insert_point2 = buf2;
	*buf2 = '\0';

	rb_sprintf(buf, form_str(RPL_ISON), me.name, source_p->name);
	len = strlen(buf);
	current_insert_point = buf + len;

	/* rfc1489 is ambigious about how to handle ISON
	 * this should handle both interpretations.
	 */
	for(i = 1; i < parc; i++)
	{
		char *cs = LOCAL_COPY(parv[i]);
		for(nick = rb_strtok_r(cs, " ", &p); nick; nick = rb_strtok_r(NULL, " ", &p))
		{
			target_p = find_named_client(nick);

			if(target_p != NULL)
			{
				len = strlen(target_p->name);
				if((current_insert_point + (len + 5)) < (buf + sizeof(buf)))
				{
					memcpy(current_insert_point, target_p->name, len);
					current_insert_point += len;
					*current_insert_point++ = ' ';
				}
				else
				{
					done = 1;
					break;
				}
			}
		}
		if(done)
			break;
	}

	/*  current_insert_point--;
	 *  Do NOT take out the trailing space, it breaks ircII
	 *  --Rodder */

	*current_insert_point = '\0';
	*current_insert_point2 = '\0';

	sendto_one_buffer(source_p, buf);

	return 0;
}
Пример #3
0
static int
sasl_visible(struct Client *client_p)
{
	struct Client *agent_p = NULL;

	if (ConfigFileEntry.sasl_service)
		agent_p = find_named_client(ConfigFileEntry.sasl_service);

	return agent_p != NULL && IsService(agent_p);
}
Пример #4
0
static int
m_authenticate(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
	int parc, const char *parv[])
{
	struct Client *agent_p = NULL;
	struct Client *saslserv_p = NULL;

	/* They really should use CAP for their own sake. */
	if(!IsCapable(source_p, CLICAP_SASL))
		return 0;

	if (strlen(client_p->id) == 3)
	{
		exit_client(client_p, client_p, client_p, "Mixing client and server protocol");
		return 0;
	}

	saslserv_p = find_named_client(ConfigFileEntry.sasl_service);
	if (saslserv_p == NULL || !IsService(saslserv_p))
	{
		sendto_one(source_p, form_str(ERR_SASLABORTED), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
		return 0;
	}

	if(source_p->localClient->sasl_complete)
	{
		*source_p->localClient->sasl_agent = '\0';
		source_p->localClient->sasl_complete = 0;
	}

	if(strlen(parv[1]) > 400)
	{
		sendto_one(source_p, form_str(ERR_SASLTOOLONG), me.name, EmptyString(source_p->name) ? "*" : source_p->name);
		return 0;
	}

	if(!*source_p->id)
	{
		/* Allocate a UID. */
		strcpy(source_p->id, generate_uid());
		add_to_id_hash(source_p->id, source_p);
	}

	if(*source_p->localClient->sasl_agent)
		agent_p = find_id(source_p->localClient->sasl_agent);

	if(agent_p == NULL)
	{
		sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s H %s %s",
					me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
					source_p->host, source_p->sockhost);

		if (source_p->certfp != NULL)
			sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s %s",
						me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
						parv[1], source_p->certfp);
		else
			sendto_one(saslserv_p, ":%s ENCAP %s SASL %s %s S %s",
						me.id, saslserv_p->servptr->name, source_p->id, saslserv_p->id,
						parv[1]);

		rb_strlcpy(source_p->localClient->sasl_agent, saslserv_p->id, IDLEN);
	}
	else
		sendto_one(agent_p, ":%s ENCAP %s SASL %s %s C %s",
				me.id, agent_p->servptr->name, source_p->id, agent_p->id,
				parv[1]);
	source_p->localClient->sasl_out++;

	return 0;
}
Пример #5
0
static int
ms_signon(struct Client *client_p, struct Client *source_p,
          int parc, const char *parv[])
{
    struct Client *target_p;
    int newts, sameuser;
    char login[NICKLEN+1];

    if(!clean_nick(parv[1])) {
        ServerStats.is_kill++;
        sendto_realops_snomask(SNO_DEBUG, L_ALL,
                               "Bad Nick from SIGNON: %s From: %s(via %s)",
                               parv[1], source_p->servptr->name, client_p->name);
        /* if source_p has an id, kill_client_serv_butone() will
         * send a kill to client_p, otherwise do it here */
        if (!has_id(source_p))
            sendto_one(client_p, ":%s KILL %s :%s (Bad nickname from SIGNON)",
                       get_id(&me, client_p), parv[1], me.name);
        kill_client_serv_butone(client_p, source_p, "%s (Bad nickname from SIGNON)",
                                me.name);
        source_p->flags |= FLAGS_KILLED;
        exit_client(NULL, source_p, &me, "Bad nickname from SIGNON");
        return 0;
    }

    if(!clean_username(parv[2]) || !clean_host(parv[3])) {
        ServerStats.is_kill++;
        sendto_realops_snomask(SNO_DEBUG, L_ALL,
                               "Bad user@host from SIGNON: %s@%s From: %s(via %s)",
                               parv[2], parv[3], source_p->servptr->name, client_p->name);
        /* if source_p has an id, kill_client_serv_butone() will
         * send a kill to client_p, otherwise do it here */
        if (!has_id(source_p))
            sendto_one(client_p, ":%s KILL %s :%s (Bad user@host from SIGNON)",
                       get_id(&me, client_p), parv[1], me.name);
        kill_client_serv_butone(client_p, source_p, "%s (Bad user@host from SIGNON)",
                                me.name);
        source_p->flags |= FLAGS_KILLED;
        exit_client(NULL, source_p, &me, "Bad user@host from SIGNON");
        return 0;
    }

    newts = atol(parv[4]);

    if(!strcmp(parv[5], "0"))
        login[0] = '\0';
    else if(*parv[5] != '*') {
        if (clean_nick(parv[5]))
            rb_strlcpy(login, parv[5], NICKLEN + 1);
        else
            return 0;
    }

    target_p = find_named_client(parv[1]);
    if(target_p != NULL && target_p != source_p) {
        /* In case of collision, follow NICK rules. */
        /* XXX this is duplicated code and does not do SAVE */
        if(IsUnknown(target_p))
            exit_client(NULL, target_p, &me, "Overridden");
        else {
            if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user) {
                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                       "Nick change collision from SIGNON from %s to %s(%s <- %s)(both killed)",
                                       source_p->name, target_p->name, target_p->from->name,
                                       client_p->name);

                ServerStats.is_kill++;
                sendto_one_numeric(target_p, ERR_NICKCOLLISION,
                                   form_str(ERR_NICKCOLLISION), target_p->name);

                kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name);

                ServerStats.is_kill++;

                kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name);

                target_p->flags |= FLAGS_KILLED;
                exit_client(NULL, target_p, &me, "Nick collision(new)");
                source_p->flags |= FLAGS_KILLED;
                exit_client(client_p, source_p, &me, "Nick collision(old)");
                return 0;
            } else {
                sameuser = !irccmp(target_p->username, source_p->username) &&
                           !irccmp(target_p->host, source_p->host);

                if((sameuser && newts < target_p->tsinfo) ||
                   (!sameuser && newts > target_p->tsinfo)) {
                    if(sameuser)
                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                               "Nick change collision from SIGNON from %s to %s(%s <- %s)(older killed)",
                                               source_p->name, target_p->name,
                                               target_p->from->name, client_p->name);
                    else
                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                               "Nick change collision from SIGNON from %s to %s(%s <- %s)(newer killed)",
                                               source_p->name, target_p->name,
                                               target_p->from->name, client_p->name);

                    ServerStats.is_kill++;

                    sendto_one_numeric(target_p, ERR_NICKCOLLISION,
                                       form_str(ERR_NICKCOLLISION), target_p->name);

                    /* kill the client issuing the nickchange */
                    kill_client_serv_butone(client_p, source_p,
                                            "%s (Nick change collision)", me.name);

                    source_p->flags |= FLAGS_KILLED;

                    if(sameuser)
                        exit_client(client_p, source_p, &me, "Nick collision(old)");
                    else
                        exit_client(client_p, source_p, &me, "Nick collision(new)");
                    return 0;
                } else {
                    if(sameuser)
                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                               "Nick collision from SIGNON on %s(%s <- %s)(older killed)",
                                               target_p->name, target_p->from->name,
                                               client_p->name);
                    else
                        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                               "Nick collision from SIGNON on %s(%s <- %s)(newer killed)",
                                               target_p->name, target_p->from->name,
                                               client_p->name);

                    sendto_one_numeric(target_p, ERR_NICKCOLLISION,
                                       form_str(ERR_NICKCOLLISION), target_p->name);

                    /* kill the client who existed before hand */
                    kill_client_serv_butone(client_p, target_p,
                                            "%s (Nick collision)", me.name);

                    ServerStats.is_kill++;

                    target_p->flags |= FLAGS_KILLED;
                    (void) exit_client(client_p, target_p, &me, "Nick collision");
                }
            }

        }
    }

    send_signon(client_p, source_p, parv[1], parv[2], parv[3], newts, login);
    return 0;
}
Пример #6
0
static void
cap_req(struct Client *source_p, const char *arg)
{
	char buf[BUFSIZE];
	char pbuf[2][BUFSIZE];
	struct clicap *cap;
	int buflen, plen;
	int i = 0;
	int capadd = 0, capdel = 0;
	int finished = 0, negate;

	if(!IsRegistered(source_p))
		source_p->flags |= FLAGS_CLICAP;

	if(EmptyString(arg))
		return;

	buflen = snprintf(buf, sizeof(buf), ":%s CAP %s ACK",
			me.name, EmptyString(source_p->name) ? "*" : source_p->name);

	pbuf[0][0] = '\0';
	plen = 0;

	for(cap = clicap_find(arg, &negate, &finished); cap;
	    cap = clicap_find(NULL, &negate, &finished))
	{
		/* filled the first array, but cant send it in case the
		 * request fails.  one REQ should never fill more than two
		 * buffers --fl
		 */
		if(buflen + plen + cap->namelen + 6 >= BUFSIZE)
		{
			pbuf[1][0] = '\0';
			plen = 0;
			i = 1;
		}

		if(negate)
		{
			if(cap->flags & CLICAP_FLAGS_STICKY)
			{
				finished = 0;
				break;
			}

			strcat(pbuf[i], "-");
			plen++;

			capdel |= cap->cap_serv;
		}
		else
		{
			if(cap->cap_required_serv && !((capadd & cap->cap_required_serv) == cap->cap_required_serv || IsCapable(source_p, cap->cap_required_serv)))
			{
				finished = 0;
				break;
			}

			if (cap->cap_serv == CLICAP_SASL)
			{
				struct Client *agent_p = NULL;

				if (!ConfigFileEntry.sasl_service)
				{
					finished = 0;
					break;
				}

				agent_p = find_named_client(ConfigFileEntry.sasl_service);
				if (agent_p == NULL || !IsService(agent_p))
				{
					finished = 0;
					break;
				}
			}

			capadd |= cap->cap_serv;
		}

		if(cap->cap_cli)
		{
			strcat(pbuf[i], "~");
			plen++;
		}

		strcat(pbuf[i], cap->name);
		if (!finished) {
			strcat(pbuf[i], " ");
			plen += (cap->namelen + 1);
		}
	}

	if(!finished)
	{
		sendto_one(source_p, ":%s CAP %s NAK :%s",
			me.name, EmptyString(source_p->name) ? "*" : source_p->name, arg);
		return;
	}

	if(i)
	{
		sendto_one(source_p, "%s * :%s", buf, pbuf[0]);
		sendto_one(source_p, "%s :%s", buf, pbuf[1]);
	}
	else
		sendto_one(source_p, "%s :%s", buf, pbuf[0]);

	source_p->localClient->caps |= capadd;
	source_p->localClient->caps &= ~capdel;
}
Пример #7
0
/* clicap_generate()
 *   Generates a list of capabilities.
 *
 * Inputs: client to send to, subcmd to send,
 *         flags to match against: 0 to do none, -1 if client has no flags,
 *         int to whether we are doing CAP CLEAR
 * Outputs: None
 */
static void
clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clear)
{
	char buf[BUFSIZE];
	char capbuf[BUFSIZE];
	char *p;
	int buflen = 0;
	int curlen, mlen;
	size_t i;

	mlen = sprintf(buf, ":%s CAP %s %s",
			me.name,
			EmptyString(source_p->name) ? "*" : source_p->name,
			subcmd);

	p = capbuf;
	buflen = mlen;

	/* shortcut, nothing to do */
	if(flags == -1)
	{
		sendto_one(source_p, "%s :", buf);
		return;
	}

	for(i = 0; i < CLICAP_LIST_LEN; i++)
	{
		if(flags)
		{
			if(!IsCapable(source_p, clicap_list[i].cap_serv))
				continue;
			/* they are capable of this, check sticky */
			else if(clear && clicap_list[i].flags & CLICAP_FLAGS_STICKY)
				continue;
		}

		if (clicap_list[i].cap_serv == CLICAP_SASL)
		{
			struct Client *agent_p = NULL;

			if (!ConfigFileEntry.sasl_service)
				continue;

			agent_p = find_named_client(ConfigFileEntry.sasl_service);
			if (agent_p == NULL || !IsService(agent_p))
				continue;
		}

		/* \r\n\0, possible "-~=", space, " *" */
		if(buflen + clicap_list[i].namelen >= BUFSIZE - 10)
		{
			/* remove our trailing space -- if buflen == mlen
			 * here, we didnt even succeed in adding one.
			 */
			if(buflen != mlen)
				*(p - 1) = '\0';
			else
				*p = '\0';

			sendto_one(source_p, "%s * :%s", buf, capbuf);
			p = capbuf;
			buflen = mlen;
		}

		if(clear)
		{
			*p++ = '-';
			buflen++;
		}

		curlen = sprintf(p, "%s ", clicap_list[i].name);
		p += curlen;
		buflen += curlen;
	}

	/* remove trailing space */
	if(buflen != mlen)
		*(p - 1) = '\0';
	else
		*p = '\0';

	sendto_one(source_p, "%s :%s", buf, capbuf);
}