예제 #1
0
/*
 * m_webirc
 * parv[0] = sender prefix
 * parv[1] = password that authenticates the WEBIRC command from this client
 * parv[2] = username or client requesting spoof (cgiirc defaults to cgiirc)
 * parv[3] = hostname of user
 * parv[4] = IP address of user
 */
int m_webirc(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    char oldusername[USERLEN + 1];
    struct userBan *ban;
    int i;

    if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
	*parv[3] == '\0' || *parv[4] == '\0')
    {
	sendto_one(&me, sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "WEBIRC");
	return 0;
    }
    if (!MyConnect(sptr) || !IsUnknown(cptr) || cptr->receiveM != 1)
    {
	sendto_one(&me, sptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
	return 0;
    }

    strncpyzt(oldusername, cptr->username, USERLEN + 1);
    make_user(cptr);
    if (!(cptr->flags & FLAGS_GOTID))
	strcpy(cptr->username, "webirc");
    i = attach_Iline(cptr, cptr->hostp, cptr->sockhost);
    if (i == 0)
    {
	aAllow *pwaconf = sptr->user->allow;

	if (BadPtr(pwaconf->passwd) ||
	    strncmp(pwaconf->passwd, "webirc.", strlen("webirc.")) != 0)
	{
	  sendto_one(&me, sptr, "NOTICE * :Not a CGI:IRC auth block");
	    i = -1;
	}
	else if (!StrEq(parv[1], pwaconf->passwd + strlen("webirc.")))
	{
	  sendto_one(&me, sptr, "NOTICE * :CGI:IRC password incorrect");
	    i = -1;
	}
	else if (pwaconf->flags & CONF_FLAGS_NOTHROTTLE)
	    throttle_remove(cptr->sockhost);
    }
    clear_conflinks(cptr);
    free_user(cptr->user, cptr);
    cptr->user = NULL;
    cptr->flags &= ~FLAGS_DOID;
    strncpyzt(cptr->username, oldusername, USERLEN + 1);
    if (i != 0)
	return 0;

    if (inet_pton(AF_INET, parv[4], &cptr->ip.ip4))
	cptr->ip_family = AF_INET;
    else if (inet_pton(AF_INET6, parv[4], &cptr->ip.ip6))
	cptr->ip_family = AF_INET6;
    else
    {
	sendto_one(&me, sptr, "NOTICE * :Invalid IP");
	return 0;
    }

    if (cptr->flags & FLAGS_GOTID)
    {
	cptr->webirc_username = MyMalloc(strlen(cptr->username) + 1);
	strcpy(cptr->webirc_username, cptr->username);
    }
    else
    {
	cptr->webirc_username = MyMalloc(strlen(parv[2]) + 1);
	strcpy(cptr->webirc_username, parv[2]);
    }
    cptr->webirc_ip = MyMalloc(strlen(cptr->sockhost) + 1);
    strcpy(cptr->webirc_ip, cptr->sockhost);

    get_sockhost(cptr, parv[3]);
    cptr->hostp = NULL;

    /*
     * Acknowledge that WEBIRC was accepted, and flush the client's send queue
     * to make debugging easier.
     */
  sendto_one(&me, sptr, ":%s NOTICE AUTH :*** CGI:IRC host/IP set to %s %s",
	       me.name, cptr->sockhost, parv[4]);
    dump_connections(cptr->fd);

    /* if they are throttled, drop them silently. */
    if (throttle_check(parv[4], cptr->fd, NOW) == 0)
    {
	cptr->flags |= FLAGS_DEADSOCKET;

	ircstp->is_ref++;
	ircstp->is_throt++;
	return exit_client(cptr, sptr, &me, "Client throttled");
    }

    ban = check_userbanned(cptr, UBAN_IP|UBAN_CIDR4|UBAN_WILDUSER, 0);
    if(ban)
    {
	int loc = (ban->flags & UBAN_LOCAL) ? 1 : 0;

	ircstp->is_ref++;
	ircstp->is_ref_2++;
	return exit_banned_client(cptr, loc, loc ? 'K' : 'A', ban->reason, 0);
    }
    return 0;
}
예제 #2
0
/*
 * ms_nick()
 *      
 * server -> server nick change
 *    parv[0] = sender prefix
 *    parv[1] = nickname
 *    parv[2] = TS when nick change
 *
 * server introducing new nick
 *    parv[0] = sender prefix
 *    parv[1] = nickname
 *    parv[2] = hop count
 *    parv[3] = TS
 *    parv[4] = umode
 *    parv[5] = username
 *    parv[6] = hostname
 *    parv[7] = server
 *    parv[8] = ircname
 */
static void
ms_nick(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Client *target_p;
	char nick[NICKLEN];
	time_t newts = 0;

	if(parc < 2 || BadPtr(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
		return;
	}

	/* parc == 3 on nickchange, parc == 9 on new nick */
	if((IsClient(source_p) && (parc != 3)) || (IsServer(source_p) && ((parc != 9) && (parc != 10))))
	{
		char tbuf[BUFSIZE] = { 0 };
		int j;

		for (j = 0; j < parc; j++)
		{
			strcat(tbuf, parv[j]);
			strcat(tbuf, " ");
		}

		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Dropping server %s due to (invalid) command 'NICK' "
				     "with only %d arguments.  (Buf: '%s')",
				     client_p->name, parc, tbuf);
		ilog(L_CRIT, "Insufficient parameters (%d) for command 'NICK' from %s.  Buf: %s",
		     parc, client_p->name, tbuf);
		exit_client(client_p, client_p, client_p,
			    "Not enough arguments to server command.");
		return;
	}

	/* fix the length of the nick */
	strlcpy(nick, parv[1], sizeof(nick));

    if ((parc == 9) || (parc == 10))
	{
		if (check_clean_nick(client_p, source_p, nick, parv[1], parv[7]))
			return;
	}
	else
	{
		if (check_clean_nick(client_p, source_p, nick, parv[1], (char *)source_p->user->server))
			return;
	}

	if(parc == 9 || parc == 10)
	{
		if(check_clean_user(client_p, nick, parv[5], parv[7]) ||
		   check_clean_host(client_p, nick, parv[6], parv[7]))
			return;

		/* check the length of the clients gecos */
		if(strlen(parv[(parc > 9)? 9 : 8]) > REALLEN)
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Long realname from server %s for %s", parv[7],
					     parv[1]);
			parv[(parc > 9)? 9 : 8][REALLEN] = '\0';
		}

		if(IsServer(source_p))
			newts = atol(parv[3]);
	}
	else
	{
		if(!IsServer(source_p))
			newts = atol(parv[2]);
	}

	/* if the nick doesnt exist, allow it and process like normal */
	if(!(target_p = find_client(nick)))
	{
		nick_from_server(client_p, source_p, parc, parv, newts, nick);
		return;
	}

	/* we're not living in the past anymore, an unknown client is local only. */
	if(IsUnknown(target_p))
	{
		exit_client(NULL, target_p, &me, "Overridden");
		nick_from_server(client_p, source_p, parc, parv, newts, nick);
		return;
	}

	if(target_p == source_p)
	{
		if(strcmp(target_p->name, nick))
		{
			/* client changing case of nick */
			nick_from_server(client_p, source_p, parc, parv, newts, nick);
			return;
		}
		else
			/* client not changing nicks at all */
			return;
	}

	perform_nick_collides(source_p, client_p, target_p, parc, parv, newts, nick);


}
예제 #3
0
static int
perform_nick_collides(struct Client *source_p, struct Client *client_p,
		      struct Client *target_p, int parc, char *parv[], time_t newts, char *nick)
{
	int sameuser;

	/* server introducing new nick */
	if(IsServer(source_p))
	{
		/* if we dont have a ts, or their TS's are the same, kill both */
		if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Nick collision on %s(%s <- %s)(both killed)",
					     target_p->name, target_p->from->name, client_p->name);

			kill_client_serv_butone(NULL, target_p,
						"%s (Nick collision (new))", me.name);
			ServerStats->is_kill++;
			sendto_one(target_p, form_str(ERR_NICKCOLLISION),
				   me.name, target_p->name, target_p->name);

			target_p->flags |= FLAGS_KILLED;
			exit_client(client_p, target_p, &me, "Nick collision (new)");
			return 0;
		}
		/* the timestamps are different */
		else
		{
			sameuser = (target_p->user) && !irccmp(target_p->username, parv[5])
				&& !irccmp(target_p->host, parv[6]);

			/* if the users are the same (loaded a client on a different server)
			 * and the new users ts is older, or the users are different and the
			 * new users ts is newer, ignore the new client and let it do the kill
			 */
			if((sameuser && newts < target_p->tsinfo) ||
			   (!sameuser && newts > target_p->tsinfo))
			{
				return 0;
			}
			else
			{
				if(sameuser)
					sendto_realops_flags(UMODE_ALL, L_ALL,
							     "Nick collision on %s(%s <- %s)(older killed)",
							     target_p->name, target_p->from->name,
							     client_p->name);
				else
					sendto_realops_flags(UMODE_ALL, L_ALL,
							     "Nick collision on %s(%s <- %s)(newer killed)",
							     target_p->name, target_p->from->name,
							     client_p->name);

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

				/* if it came from a LL server, itd have been source_p,
				 * so we dont need to mark target_p as known
				 */
				kill_client_serv_butone(source_p, target_p,
							"%s (Nick collision (new))", me.name);

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

				nick_from_server(client_p, source_p, parc, parv, newts, nick);
				return 0;
			}
		}
	}

	/* its a client changing nick and causing a collide */
	if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user)
	{
		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Nick change collision 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(target_p, form_str(ERR_NICKCOLLISION),
			   me.name, target_p->name, target_p->name);

		/* if we got the message from a LL, it knows about source_p */
		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_flags(UMODE_ALL, L_ALL,
						     "Nick change collision from %s to %s(%s <- %s)(older killed)",
						     source_p->name, target_p->name,
						     target_p->from->name, client_p->name);
			else
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick change collision from %s to %s(%s <- %s)(newer killed)",
						     source_p->name, target_p->name,
						     target_p->from->name, client_p->name);

			ServerStats->is_kill++;

			/* this won't go back to the incoming link, so LL doesnt matter */
			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_flags(UMODE_ALL, L_ALL,
						     "Nick collision on %s(%s <- %s)(older killed)",
						     target_p->name, target_p->from->name,
						     client_p->name);
			else
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick collision on %s(%s <- %s)(newer killed)",
						     target_p->name, target_p->from->name,
						     client_p->name);

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

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

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

	/* we should only ever call nick_from_server() here, as
	 * this is a client changing nick, not a new client
	 */
	nick_from_server(client_p, source_p, parc, parv, newts, nick);

	return 0;
}
예제 #4
0
/*
 * handle_command
 *
 * inputs	- pointer to message block
 *		- pointer to client
 *		- pointer to client message is from
 *		- count of number of args
 *		- pointer to argv[] array
 * output	- -1 if error from server
 * side effects	-
 */
static int
handle_command(struct Message *mptr, struct Client *client_p,
	       struct Client *from, int i, const char **hpara)
{
	struct MessageEntry ehandler;
	MessageHandler handler = 0;

	if(IsAnyDead(client_p))
		return -1;

	if(IsServer(client_p))
		mptr->rcount++;

	mptr->count++;

	/* New patch to avoid server flooding from unregistered connects
	   - Pie-Man 07/27/2000 */

	if(!IsRegistered(client_p))
	{
		/* if its from a possible server connection
		 * ignore it.. more than likely its a header thats sneaked through
		 */

		if(IsAnyServer(client_p) && !(mptr->flags & MFLG_UNREG))
			return (1);
	}

	ehandler = mptr->handlers[from->handler];
	handler = ehandler.handler;

	/* check right amount of params is passed... --is */
	if(i < ehandler.min_para || 
	   (ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1])))
	{
		if(!IsServer(client_p))
		{
			sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
				   me.name, 
				   EmptyString(client_p->name) ? "*" : client_p->name, 
				   mptr->cmd);
			if(MyClient(client_p))
				return (1);
			else
				return (-1);
		}

		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Dropping server %s due to (invalid) command '%s'"
				     " with only %d arguments (expecting %d).",
				     client_p->name, mptr->cmd, i, ehandler.min_para);
		ilog(L_SERVER,
		     "Insufficient parameters (%d) for command '%s' from %s.",
		     i, mptr->cmd, client_p->name);

		exit_client(client_p, client_p, client_p,
			    "Not enough arguments to server command.");
		return (-1);
	}

	(*handler) (client_p, from, i, hpara);
	return (1);
}
예제 #5
0
/*
 * m_nick()
 *
 *     parv[0] = sender prefix
 *     parv[1] = nickname
 */
static void
m_nick(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	char nick[NICKLEN];
	struct Client *target_p;

	if(parc < 2 || BadPtr(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
		return;
	}

	/* mark end of grace period, to prevent nickflooding */
	if(!IsFloodDone(source_p))
		flood_endgrace(source_p);

	/* terminate nick to NICKLEN */
	strlcpy(nick, parv[1], sizeof(nick));

	/* check the nickname is ok */
	if(!clean_nick_name(nick))
	{
		sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], nick);
		return;
	}

	if(find_nick_resv(nick))
	{
		sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
			   me.name, parv[0], nick);
		return;
	}

	if((target_p = find_client(nick)))
	{
		/* If(target_p == source_p) the client is changing nicks between
		 * equivalent nicknames ie: [nick] -> {nick}
		 */

		if(target_p == source_p)
		{
			/* check the nick isnt exactly the same */
			if(strcmp(target_p->name, nick))
			{
				change_local_nick(client_p, source_p, nick);
				return;
			}
			else
			{
				/* client is doing :old NICK old
				 * ignore it..
				 */
				return;
			}
		}

		/* if the client that has the nick isnt registered yet (nick but no
		 * user) then drop the unregged client
		 */
		if(IsUnknown(target_p))
		{
			/* the old code had an if(MyConnect(target_p)) here.. but I cant see
			 * how that can happen, m_nick() is local only --fl_
			 */

			exit_client(NULL, target_p, &me, "Overridden");
			change_local_nick(client_p, source_p, nick);
			return;
		}
		else
		{
			sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, parv[0], nick);
			return;
		}

	}
	else
	{
		change_local_nick(client_p, source_p, nick);
		return;
	}
}
예제 #6
0
static int
me_svslogin(struct Client *client_p, struct Client *source_p,
	int parc, const char *parv[])
{
	struct Client *target_p, *exist_p;
	char nick[NICKLEN+1], login[NICKLEN+1];
	char user[USERLEN+1], host[HOSTLEN+1];
	int valid = 0;

	if(!(source_p->flags & FLAGS_SERVICE))
		return 0;

	if((target_p = find_client(parv[1])) == NULL)
		return 0;

	if(!MyClient(target_p) && !IsUnknown(target_p))
		return 0;

	if(clean_nick(parv[2]))
	{
		rb_strlcpy(nick, parv[2], NICKLEN + 1);
		valid |= NICK_VALID;
	}
	else if(*target_p->name)
		rb_strlcpy(nick, target_p->name, NICKLEN + 1);
	else
		strcpy(nick, "*");

	if(clean_username(parv[3]))
	{
		rb_strlcpy(user, parv[3], USERLEN + 1);
		valid |= USER_VALID;
	}
	else
		rb_strlcpy(user, target_p->username, USERLEN + 1);

	if(clean_host(parv[4]))
	{
		rb_strlcpy(host, parv[4], HOSTLEN + 1);
		valid |= HOST_VALID;
	}
	else
		rb_strlcpy(host, target_p->host, HOSTLEN + 1);

	if(*parv[5] == '*')
	{
		if(target_p->user)
			rb_strlcpy(login, target_p->user->suser, NICKLEN + 1);
		else
			login[0] = '\0';
	}
	else if(!strcmp(parv[5], "0"))
		login[0] = '\0';
	else
		rb_strlcpy(login, parv[5], NICKLEN + 1);

	/* Login (mostly) follows nick rules. */
	if(*login && !clean_nick(login))
		return 0;

	if((exist_p = find_person(nick)) && target_p != exist_p)
	{
		char buf[BUFSIZE];

		if(MyClient(exist_p))
			sendto_one(exist_p, ":%s KILL %s :(Nickname regained by services)",
				me.name, exist_p->name);

		exist_p->flags |= FLAGS_KILLED;
		kill_client_serv_butone(NULL, exist_p, "%s (Nickname regained by services)",
					me.name);
		sendto_realops_snomask(SNO_SKILL, L_ALL,
				"Nick collision due to SVSLOGIN on %s",
				nick);

		rb_snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))",
			me.name);
		exit_client(NULL, exist_p, &me, buf);
	}else if((exist_p = find_client(nick)) && IsUnknown(exist_p) && exist_p != target_p) {
		exit_client(NULL, exist_p, &me, "Overridden");
	}

	if(*login)
	{
		/* Strip leading digits, unless it's purely numeric. */
		const char *p = login;
		while(IsDigit(*p))
			p++;
		if(!*p)
			p = login;

		sendto_one(target_p, form_str(RPL_LOGGEDIN), me.name, EmptyString(target_p->name) ? "*" : target_p->name,
				nick, user, host, p, p);
	}
	else
		sendto_one(target_p, form_str(RPL_LOGGEDOUT), me.name, EmptyString(target_p->name) ? "*" : target_p->name,
				nick, user, host);

	if(IsUnknown(target_p))
	{
		struct User *user_p = make_user(target_p);

		if(valid & NICK_VALID)
			strcpy(target_p->preClient->spoofnick, nick);

		if(valid & USER_VALID)
			strcpy(target_p->preClient->spoofuser, user);

		if(valid & HOST_VALID)
			strcpy(target_p->preClient->spoofhost, host);

		rb_strlcpy(user_p->suser, login, NICKLEN + 1);
	}
	else
	{
		char note[NICKLEN + 10];

		send_signon(NULL, target_p, nick, user, host, rb_current_time(), login);

		rb_snprintf(note, NICKLEN + 10, "Nick: %s", target_p->name);
		rb_note(target_p->localClient->F, note);
	}

	return 0;
}
예제 #7
0
/*
 * mr_capab - CAPAB message handler
 *      parv[0] = sender prefix
 *      parv[1] = space-separated list of capabilities
 *
 */
static void
mr_capab(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
    struct Capability *cap;
    int i;
    char *p;
    char *s;
#ifdef HAVE_LIBCRYPTO
    struct EncCapability *ecap;
    unsigned int cipher = 0;
#endif

    /* ummm, this shouldn't happen. Could argue this should be logged etc. */
    if(client_p->localClient == NULL)
        return;

    if(client_p->localClient->caps)
    {
        exit_client(client_p, client_p, client_p, "CAPAB received twice");
        return;
    }
    else
        client_p->localClient->caps |= CAP_CAP;

    for (i = 1; i < parc; i++)
    {
        for (s = strtoken(&p, parv[i], " "); s; s = strtoken(&p, NULL, " "))
        {
#ifdef HAVE_LIBCRYPTO
            if((strncmp(s, "ENC:", 4) == 0))
            {
                /* Skip the "ENC:" portion */
                s += 4;

                /* Check the remaining portion against the list of ciphers we
                 * have available (CipherTable).
                 */
                for (ecap = CipherTable; ecap->name; ecap++)
                {
                    if((!irccmp(ecap->name, s)) && (ecap->cap & CAP_ENC_MASK))
                    {
                        cipher = ecap->cap;
                        break;
                    }
                }
                /* Since the name and capabilities matched, use it. */
                if(cipher != 0)
                {
                    SetCapable(client_p, CAP_ENC);
                    client_p->localClient->enc_caps |= cipher;
                }
                else
                {
                    /* cipher is still zero; we didn't find a matching entry. */
                    exit_client(client_p, client_p, client_p,
                                "Cipher selected is not available here.");
                    return;
                }
            }
            else	/* normal capab */
#endif
                for (cap = captab; cap->name; cap++)
                {
                    if(!irccmp(cap->name, s))
                    {
                        client_p->localClient->caps |= cap->cap;
                        break;
                    }
                }
        }		/* for */
    }			/* for */
}
예제 #8
0
파일: s_conf.c 프로젝트: kisserlb/enet-1.0
/** Reload the configuration file.
 * @param cptr Client that requested rehash (if a signal, &me).
 * @param sig Type of rehash (0 = oper-requested, 1 = signal, 2 =
 *   oper-requested but do not restart resolver)
 * @return CPTR_KILLED if any client was K/G-lined because of the
 * rehash; otherwise 0.
 */
int rehash(struct Client *cptr, int sig)
{
  struct ConfItem** tmp = &GlobalConfList;
  struct ConfItem*  tmp2;
  struct Client*    acptr;
  int               i;
  int               ret = 0;
  int               found_g = 0;

  if (1 == sig)
    sendto_opmask_butone(0, SNO_OLDSNO,
                         "Got signal SIGHUP, reloading ircd conf. file");

  while ((tmp2 = *tmp)) {
    if (tmp2->clients) {
      /*
       * Configuration entry is still in use by some
       * local clients, cannot delete it--mark it so
       * that it will be deleted when the last client
       * exits...
       */
      if (CONF_CLIENT == (tmp2->status & CONF_CLIENT))
        tmp = &tmp2->next;
      else {
        *tmp = tmp2->next;
        tmp2->next = 0;
      }
      tmp2->status |= CONF_ILLEGAL;
    }
    else {
      *tmp = tmp2->next;
      free_conf(tmp2);
    }
  }
  conf_erase_crule_list();
  conf_erase_deny_list();
  conf_erase_webirc_list();
  conf_erase_shost_list();
  conf_erase_except_list();
  motd_clear();

  /*
   * delete the juped nicks list
   */
  clearNickJupes();

  clear_quarantines();

  class_mark_delete();
  mark_listeners_closing();
  auth_mark_closing();
  close_mappings();

  read_configuration_file();

  if (sig != 2)
    restart_resolver();

  log_reopen(); /* reopen log files */

  auth_close_unused();
  close_listeners();
  class_delete_marked();         /* unless it fails */

  /*
   * Flush out deleted I and P lines although still in use.
   */
  for (tmp = &GlobalConfList; (tmp2 = *tmp);) {
    if (CONF_ILLEGAL == (tmp2->status & CONF_ILLEGAL)) {
      *tmp = tmp2->next;
      tmp2->next = NULL;
      if (!tmp2->clients)
        free_conf(tmp2);
    }
    else
      tmp = &tmp2->next;
  }

  for (i = 0; i <= HighestFd; i++) {
    if ((acptr = LocalClientArray[i])) {
      assert(!IsMe(acptr));
      if (IsServer(acptr))
        det_confs_butmask(acptr, ~(CONF_UWORLD | CONF_ILLEGAL));
      /* Because admin's are getting so uppity about people managing to
       * get past K/G's etc, we'll "fix" the bug by actually explaining
       * whats going on.
       */
      if ((found_g = find_kill(acptr))) {
        sendto_opmask_butone(0, found_g > -1 ? SNO_GLINE : SNO_OPERKILL,
                             found_g == -2 ? "G-line active for %s%s" :
                             (found_g == -3 ? "Z-line active for %s%s" :
                             "K-line active for %s%s"),
                             IsUnknown(acptr) ? "Unregistered Client ":"",
                             get_client_name(acptr, SHOW_IP));
        if (exit_client(cptr, acptr, &me, found_g == -2 ? "G-lined" :
            (found_g == -3 ? "Z-lined" : "K-lined")) == CPTR_KILLED)
          ret = CPTR_KILLED;
      }
    }
  }

  attach_conf_uworld(&me);

  geoip_init();

  auth_send_event("rehash", NULL);

  return ret;
}
예제 #9
0
/* COLLIDE emits different messages to KILL. It should make services
 * kills easier to distinguish from oper kills (and aid in logging).
 * This is for purely server-generated collisions, it can never come
 * from a user.
 *
 * It's also much simpler and transfers less data across the network
 */
int m_collide(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client*    acptr;
  char*       user;
  const char* reason;
  int         chasing = 0;
  static char collide_reason[BUFSIZE];

  if (!IsServer(sptr))
    {
      sendto_one(sptr, form_str(ERR_UNKNOWNCOMMAND),
                 me.name, parv[0], "COLLIDE");
      return 0;
    }

  if (parc < 2)
    return 0;

  user = parv[1];
  reason = parc > 2 ? parv[2] : "<No reason given>";

  if (!(acptr = find_client(user, NULL)))
    {
      /*
      ** If the user has recently changed nick, we automaticly
      ** rewrite the KILL for this new nickname--this keeps
      ** servers in synch when nick change and kill collide
      */
      if (!(acptr = get_history(user, (long)KILLCHASETIMELIMIT)))
        return 0;
      chasing = 1;
    }

  if (IsServer(acptr) || IsMe(acptr))
    {
      sendto_one(sptr, form_str(ERR_CANTKILLSERVER),
                 me.name, parv[0]);
      sendto_ops_flag(UMODE_DEBUG, "COLLIDE for %s from %s (rejected, is server)",
                      acptr->name, sptr->name);
      return 0;
    }

  sendto_local_ops_flag(UMODE_DEBUG,
                        "Received COLLIDE message for %s from %s (%s)",
                        acptr->name, sptr->name, reason);

  sendto_serv_butone(cptr, ":%s COLLIDE %s :%s",
                     parv[0], acptr->name, reason);
  if (chasing && IsServer(cptr))
    sendto_one(cptr, ":%s COLLIDE %s :%s",
               me.name, acptr->name, reason);
  acptr->flags |= FLAGS_KILLED;

  /*
  ** Tell the victim she/he has been zapped, but *only* if
  ** the victim is on current server--no sense in sending the
  ** notification chasing the above kill, it won't get far
  ** anyway (as this user don't exist there any more either)
  */
  if (MyConnect(acptr))
    sendto_one(acptr, ":%s KILL %s :%s",
               parv[0], acptr->name, reason);

  ircsnprintf(collide_reason, 512, "Collided by %s (%s)", sptr->name, reason);
  return exit_client(cptr, acptr, sptr, collide_reason);
}
예제 #10
0
/*
** m_quit
**	parv[0] = sender prefix
**	parv[1] = comment
*/
DLLFUNC int  m_quit(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	char *ocomment = (parc > 1 && parv[1]) ? parv[1] : parv[0];
	static char comment[TOPICLEN + 1];
	Membership *lp;

	if (!IsServer(cptr) && IsPerson(sptr))
	{
#ifdef STRIPBADWORDS
		int blocked = 0;
#endif
		int n;
		char *s = comment;
		Hook *tmphook;
		if (STATIC_QUIT)
			return exit_client(cptr, sptr, sptr, STATIC_QUIT);
		if (IsVirus(sptr))
			return exit_client(cptr, sptr, sptr, "Client exited");

		if (!prefix_quit || strcmp(prefix_quit, "no"))
			s = ircsprintf(comment, "%s ",
		    		BadPtr(prefix_quit) ? "Quit:" : prefix_quit);
#ifdef STRIPBADWORDS
		ocomment = (char *)stripbadwords_quit(ocomment, &blocked);
		if (blocked)
			ocomment = parv[0];
#endif
		n = dospamfilter(sptr, ocomment, SPAMF_QUIT, NULL, 0, NULL);
		if (n == FLUSH_BUFFER)
			return n;
		if (n < 0)
			ocomment = parv[0];
		
		if (!IsAnOper(sptr) && ANTI_SPAM_QUIT_MSG_TIME)
			if (sptr->firsttime+ANTI_SPAM_QUIT_MSG_TIME > TStime())
				ocomment = parv[0];

		/* Strip color codes if any channel is +S, use nick as reason if +c. */
		if (IsPerson(sptr) && (strchr(ocomment, '\003')))
		{
			unsigned char filtertype = 0; /* 1=filter, 2=block, highest wins. */
			for (lp = sptr->user->channel; lp; lp = lp->next)
			{
				if (lp->chptr->mode.mode & MODE_NOCOLOR)
				{
					filtertype = 2;
					break;
				}
				if (lp->chptr->mode.mode & MODE_STRIP)
				{
					if (!filtertype)
						filtertype = 1;
				}
			}
			if (filtertype == 1)
			{
				ocomment = StripColors(ocomment);
				if (*ocomment == '\0')
					ocomment = parv[0];
			} else
			if (filtertype == 2)
				ocomment = parv[0];
		} /* (strip color codes) */

                for (tmphook = Hooks[HOOKTYPE_PRE_LOCAL_QUIT]; tmphook; tmphook = tmphook->next)
		{
                	ocomment = (*(tmphook->func.pcharfunc))(sptr, ocomment);
                        if (!ocomment)
			{			
				ocomment = parv[0];
                                break;
                        }
                }

		strncpy(s, ocomment, TOPICLEN - (s - comment));
		comment[TOPICLEN] = '\0';
		return exit_client(cptr, sptr, sptr, comment);
	}
	else
	{
		return exit_client(cptr, sptr, sptr, ocomment);
	}
}
예제 #11
0
/*
 *Main thread for each client.  Receives all messages
 *and passes the data off to the correct function.  Receives
 *a pointer to the file descriptor for the socket the thread
 *should listen on
 */
void *client_receive(void *ptr) {
   int client = *(int *) ptr;
   int received;
   int logged_in = 0;
   packet in_pkt, *client_message_ptr = &in_pkt;

   while (1) {
      received = recv(client, &in_pkt, sizeof(packet), 0);
      if (received) {
         debugPacket(client_message_ptr);

         // Responses to not logged in clients
         if (!logged_in) {
            if(in_pkt.options == REGISTER) {
               logged_in = register_user(&in_pkt, client);
            }
            else if(in_pkt.options == LOGIN) {
               logged_in = login(&in_pkt, client);
            }
            else if(in_pkt.options == EXIT) {
               close(client);
               return NULL;
            }
            else {
               sendError("Not logged in.", client);
            }
         }

         // Responses to logged in clients
         else if (logged_in) {
            // Handle option messages for logged in client
            if (in_pkt.options < 1000) {
               if(in_pkt.options == REGISTER) { 
                  sendError("You may not register while logged in.", client);
               }
               else if(in_pkt.options == SETPASS) {
                  set_pass(&in_pkt, client);
               }
               else if(in_pkt.options == SETNAME) {
                  set_name(&in_pkt, client);
               }
               else if(in_pkt.options == LOGIN) {
                  sendError("Already logged in.", client);
               }
               else if(in_pkt.options == EXIT) {
                  exit_client(&in_pkt, client);
                  return NULL;
               }
               else if(in_pkt.options == INVITE) {
                  invite(&in_pkt, client);
               }
               else if(in_pkt.options == JOIN) {
                  join(&in_pkt, client);
               }
               else if(in_pkt.options == LEAVE) {
                  leave(&in_pkt, client);
               }
               else if(in_pkt.options == GETALLUSERS) {
                  get_active_users(client);
               }
               else if(in_pkt.options == GETUSERS) {
                  get_room_users(&in_pkt, client);
               }
               else if(in_pkt.options == GETUSER) {
                  user_lookup(&in_pkt, client);
               }
               else if(in_pkt.options == GETROOMS) {
                  get_room_list(client);
               }
               else if(in_pkt.options == GETMOTD) {
                  sendMOTD(client);
               }
               else if(in_pkt.options == 0) {
                  printf("%s --- Error:%s Abrupt disconnect on logged in client.\n", RED, NORMAL);
                  exit_client(&in_pkt, client);
                  return NULL;
               }
               else {
                  printf("%s --- Error:%s Unknown message received from client.\n", RED, NORMAL);
	       }
            }
            // Handle conversation message for logged in client
            else {
               // Will be treated as a message packet, safe to santize entire buffer
               sanitizeInput((void *)&in_pkt.buf, 0);
               send_message(&in_pkt, client);
            }
         }

         memset(&in_pkt, 0, sizeof(packet));
      }
   }
   return NULL;
}
예제 #12
0
/*
 * mr_server - SERVER message handler
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = serverinfo/hopcount
 *      parv[3] = serverinfo
 */
static void mr_server(struct Client *client_p, struct Client *source_p,
                      int parc, char *parv[])
{
  char             info[REALLEN + 1];
  char             *name;
  struct Client    *target_p;
  int hop;

  if (parc < 4)
    {
      sendto_one(client_p,"ERROR :No servername");
      exit_client(client_p, client_p, client_p, "Wrong number of args");
      return;
    }

  name = parv[1];
  hop = atoi(parv[2]);
  strlcpy(info, parv[3], REALLEN);

  /* 
   * Reject a direct nonTS server connection if we're TS_ONLY -orabidoo
   */
  if (!DoesTS(client_p))
    {
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,"Link %s dropped, non-TS server",
			   get_client_name(client_p, HIDE_IP));
      sendto_realops_flags(FLAGS_ALL, L_OPER,"Link %s dropped, non-TS server",
			   get_client_name(client_p, MASK_IP));
      exit_client(client_p, client_p, client_p, "Non-TS server");
      return;
    }

  if (bogus_host(name))
  {
    exit_client(client_p, client_p, client_p, "Bogus server name");
    return;
  }

  /* Now we just have to call check_server and everything should be
   * check for us... -A1kmm. */
  switch (check_server(name, client_p, CHECK_SERVER_NOCRYPTLINK))
  {
    case -1:
      if (ConfigFileEntry.warn_no_nline)
      {
        sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: No entry for "
           "servername %s", get_client_name(client_p, HIDE_IP), name);

        sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: No entry for "
           "servername %s", get_client_name(client_p, MASK_IP), name);
      }
      
      exit_client(client_p, client_p, client_p, "Invalid servername.");
      return;
      /* NOT REACHED */
      break;
      
    case -2:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: Bad password "
           "for server %s", get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: Bad password "
           "for server %s", get_client_name(client_p, MASK_IP), name);

      exit_client(client_p, client_p, client_p, "Invalid password.");
      return;
      /* NOT REACHED */
      break;
      
    case -3:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: Invalid host "
           "for server %s", get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: Invalid host "
           "for server %s", get_client_name(client_p, MASK_IP), name);

      exit_client(client_p, client_p, client_p, "Invalid host.");
      return;
      /* NOT REACHED */
      break;
    
    /* servername is > HOSTLEN */
    case -4:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
                           "Invalid servername %s from %s",
			   name, get_client_name(client_p, HIDE_IP));
      sendto_realops_flags(FLAGS_ALL, L_OPER,
		           "Invalid servername %s from %s",
			   name, get_client_name(client_p, MASK_IP));

      exit_client(client_p, client_p, client_p, "Invalid servername.");
      return;
      /* NOT REACHED */
      break;
  }
    
  if ((target_p = server_exists(name)))
    {
      /*
       * This link is trying feed me a server that I already have
       * access through another path -- multiple paths not accepted
       * currently, kill this link immediately!!
       *
       * Rather than KILL the link which introduced it, KILL the
       * youngest of the two links. -avalon
       *
       * Definitely don't do that here. This is from an unregistered
       * connect - A1kmm.
       */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
         "Attempt to re-introduce server %s from %s", name,
         get_client_name(client_p, HIDE_IP));

      sendto_realops_flags(FLAGS_ALL, L_OPER,
         "Attempt to re-introduce server %s from %s", name,
         get_client_name(client_p, MASK_IP));

      sendto_one(client_p, "ERROR :Server already exists.");
      exit_client(client_p, client_p, client_p, "Server Exists");
      return;
    }

  if(ServerInfo.hub && IsCapable(client_p, CAP_LL))
    {
      if(IsCapable(client_p, CAP_HUB))
        {
          ClearCap(client_p,CAP_LL);
          sendto_realops_flags(FLAGS_ALL, L_ALL,
               "*** LazyLinks to a hub from a hub, thats a no-no.");
        }
      else
        {
          client_p->localClient->serverMask = nextFreeMask();

          if(!client_p->localClient->serverMask)
            {
              sendto_realops_flags(FLAGS_ALL, L_ALL,
                                   "serverMask is full!");
              /* try and negotiate a non LL connect */
              ClearCap(client_p,CAP_LL);
            }
        }
    }
  else if (IsCapable(client_p, CAP_LL))
    {
      if(!IsCapable(client_p, CAP_HUB))
        {
          ClearCap(client_p,CAP_LL);
          sendto_realops_flags(FLAGS_ALL, L_ALL,
               "*** LazyLinks to a leaf from a leaf, thats a no-no.");
        }
    }

  /*
   * if we are connecting (Handshake), we already have the name from the
   * C:line in client_p->name
   */

  strlcpy(client_p->name, name, HOSTLEN+1);
  set_server_gecos(client_p, info);
  client_p->hopcount = hop;
  server_estab(client_p);
}
예제 #13
0
/*
 * ms_server - SERVER message handler
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = serverinfo/hopcount
 *      parv[3] = serverinfo
 */
static void ms_server(struct Client *client_p, struct Client *source_p,
                      int parc, char *parv[])
{
  char             info[REALLEN + 1];
                   /* same size as in s_misc.c */
  char*            name;
  struct Client*   target_p;
  struct Client*   bclient_p;
  struct ConfItem* aconf;
  int              hop;
  int              hlined = 0;
  int              llined = 0;
  dlink_node	   *ptr;

  /* Just to be sure -A1kmm. */
  if (!IsServer(source_p))
   return;

  if (parc < 4)
    {
      sendto_one(client_p,"ERROR :No servername");
      return;
    }

  name = parv[1];
  hop = atoi(parv[2]);
  strlcpy(info, parv[3], REALLEN);

  if ((target_p = server_exists(name)))
    {
      /*
       * This link is trying feed me a server that I already have
       * access through another path -- multiple paths not accepted
       * currently, kill this link immediately!!
       *
       * Rather than KILL the link which introduced it, KILL the
       * youngest of the two links. -avalon
       *
       * I think that we should exit the link itself, not the introducer,
       * and we should always exit the most recently received(i.e. the
       * one we are receiving this SERVER for. -A1kmm
       *
       * You *cant* do this, if you link somewhere, it bursts you a server
       * that already exists, then sends you a client burst, you squit the
       * server, but you keep getting the burst of clients on a server that
       * doesnt exist, although ircd can handle it, its not a realistic
       * solution.. --fl_ 
       */
      /* It is behind a host-masked server. Completely ignore the
       * server message(don't propagate or we will delink from whoever
       * we propagate to). -A1kmm */
      if (irccmp(target_p->name, name) && target_p->from==client_p)
        return;

      sendto_one(client_p, "ERROR :Server %s already exists", name);
	
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
	                   "Link %s cancelled, server %s already exists",
		 	   get_client_name(client_p, SHOW_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER,
	                   "Link %s cancelled, server %s already exists",
		 	   client_p->name, name);
      
        exit_client(client_p, client_p, &me, "Server Exists");
	return;
    }
  
  /* 
   * User nicks never have '.' in them and server names
   * must always have '.' in them.
   */
  if (strchr(name,'.') == NULL)
    {
      /*
       * Server trying to use the same name as a person. Would
       * cause a fair bit of confusion. Enough to make it hellish
       * for a while and servers to send stuff to the wrong place.
       */
      sendto_one(client_p,"ERROR :Nickname %s already exists!", name);
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
			   "Link %s cancelled: Server/nick collision on %s",
		/* inpath */ get_client_name(client_p, HIDE_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER,
          "Link %s cancelled: Server/nick collision on %s",
	  get_client_name(client_p, MASK_IP), name);
      exit_client(client_p, client_p, client_p, "Nick as Server");
      return;
    }

  /*
   * Server is informing about a new server behind
   * this link. Create REMOTE server structure,
   * add it to list and propagate word to my other
   * server links...
   */
  if (parc == 1 || info[0] == '\0')
    {
      sendto_one(client_p, "ERROR :No server info specified for %s", name);
      return;
    }

  /*
   * See if the newly found server is behind a guaranteed
   * leaf. If so, close the link.
   *
   */

  for (aconf = ConfigItemList; aconf; aconf=aconf->next)
    {
     if ((aconf->status & (CONF_LEAF|CONF_HUB)) == 0)
       continue;

     if (match(aconf->name, client_p->name))
       {
        if (aconf->status == CONF_HUB)
	  {
	    if(match(aconf->host, name))
	      hlined++;
	  }
        else if (aconf->status == CONF_LEAF)
	  {
	    if(match(aconf->host, name))
	      llined++;
	  }
       }
    }

  /* Ok, this way this works is
   *
   * A server can have a CONF_HUB allowing it to introduce servers
   * behind it.
   *
   * connect {
   *            name = "irc.bighub.net";
   *            hub_mask="*";
   *            ...
   * 
   * That would allow "irc.bighub.net" to introduce anything it wanted..
   *
   * However
   *
   * connect {
   *            name = "irc.somehub.fi";
   *		hub_mask="*";
   *		leaf_mask="*.edu";
   *...
   * Would allow this server in finland to hub anything but
   * .edu's
   */

  /* Ok, check client_p can hub the new server, and make sure it's not a LL */
  if (!hlined || (IsCapable(client_p, CAP_LL) && !IsCapable(client_p, CAP_HUB)))
    {
      /* OOOPs nope can't HUB */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
                get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
          "Non-Hub link %s introduced %s.",
	  get_client_name(client_p, MASK_IP), name);

      exit_client(NULL, source_p, &me, "No matching hub_mask.");
      return;
    }

  /* Check for the new server being leafed behind this HUB */
  if (llined)
    {
      /* OOOPs nope can't HUB this leaf */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
            "Link %s introduced leafed server %s.",
	    get_client_name(client_p, HIDE_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER, 
            "Link %s introduced leafed server %s.",
            client_p->name, name);
      /* If it is new, we are probably misconfigured, so split the
       * non-hub server introducing this. Otherwise, split the new
       * server. -A1kmm.
       */
      /* wastes too much bandwidth, generates too many errors on
       * larger networks, dont bother. --fl_
       */
#if 0
      if ((CurrentTime - source_p->firsttime) < 20)
        {
          exit_client(NULL, source_p, &me, "Leafed Server.");
          return;
        }
      else
        {
          sendto_one(source_p, ":%s SQUIT %s :Sorry, Leafed server.",
                     me.name, name);
          return;
        }
#endif

      exit_client(NULL, client_p, &me, "Leafed Server.");
      return;
    }
  
  if(strlen(name) > HOSTLEN)
  {
    sendto_realops_flags(FLAGS_ALL, L_ADMIN,
 		         "Link %s introduced server with invalid servername %s",
		         get_client_name(client_p, HIDE_IP), name);
    sendto_realops_flags(FLAGS_ALL, L_OPER,
		         "Link %s introduced server with invalid servername %s",
			 client_p->name, name);
    
    exit_client(NULL, client_p, &me, "Invalid servername introduced.");
    return;
  }

  target_p = make_client(client_p);
  make_server(target_p);
  target_p->hopcount = hop;

  strlcpy(target_p->name, name, HOSTLEN+1);
  
  set_server_gecos(target_p, info);

  target_p->serv->up = find_or_add(parv[0]);
  target_p->servptr = source_p;

  SetServer(target_p);

  Count.server++;

  add_client_to_list(target_p);
  add_server_to_list(target_p);
  add_to_client_hash_table(target_p->name, target_p);
  add_client_to_llist(&(target_p->servptr->serv->servers), target_p);


  /*
   * Old sendto_serv_but_one() call removed because we now
   * need to send different names to different servers
   * (domain name matching)
   */
  for (ptr = serv_list.head; ptr; ptr = ptr->next)
    {
      bclient_p = ptr->data;

      if (bclient_p == client_p)
	continue;
      if (!(aconf = bclient_p->serv->sconf))
	{
	  sendto_realops_flags(FLAGS_ALL, L_ADMIN, 
	        "Lost N-line for %s on %s. Closing",
		get_client_name(client_p, HIDE_IP), name);
	  sendto_realops_flags(FLAGS_ALL, L_OPER, 
	        "Lost N-line for %s on %s. Closing",
		get_client_name(client_p, MASK_IP), name);
	  exit_client(client_p, client_p, client_p, "Lost N line");
          return;
	}
      if (match(my_name_for_link(me.name, aconf), target_p->name))
	continue;

      sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
		 parv[0], target_p->name, hop + 1,
		 target_p->hidden_server ? "(H) " : "",
		 target_p->info);
    }
    
  if (!IsRelay(target_p))  
  	sendto_realops_flags(FLAGS_EXTERNAL, L_ALL,
                       "Server %s being introduced by %s",
		       			target_p->name, source_p->name);
}
예제 #14
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;
}
예제 #15
0
파일: s_auth.c 프로젝트: ahf/irc
/*
 * read_iauth
 *
 *	read and process data from the authentication slave process.
 */
void	read_iauth(void)
{
    static char obuf[READBUF_SIZE+1], last = '?';
    static int olen = 0, ia_dbg = 0;
    char buf[READBUF_SIZE+1], *start, *end, tbuf[BUFSIZ];
    aClient *cptr;
    int i;

    if (adfd == -1)
	{
	    olen = 0;
	    return;
	}
    while (1)
	{
	    if (olen)
		    bcopy(obuf, buf, olen);
	    if ((i = recv(adfd, buf+olen, READBUF_SIZE-olen, 0)) <= 0)
		{
		    if (errno != EAGAIN && errno != EWOULDBLOCK)
			{
			    sendto_flag(SCH_AUTH, "Aiiie! lost slave authentication process (errno = %d)", errno);
			    close(adfd);
			    adfd = -1;
			    olen = 0;
			    start_iauth(0);
			}
		    break;
		}
	    olen += i;
	    buf[olen] = '\0';
	    start = buf;
	    while ((end = index(start, '\n')))
		{
		    *end++ = '\0';
		    last = *start;
		    if (*start == '>')
			{
			    sendto_flag(SCH_AUTH, "%s", start+1);
			    start = end;
			    continue;
			}
		    if (*start == 'G')
			{
			    ia_dbg = atoi(start+2);
			    if (ia_dbg)
				    sendto_flag(SCH_AUTH,"ia_dbg = %d",ia_dbg);
			    start = end;
			    continue;
			}
		    if (*start == 'O') /* options */
			{
			    iauth_options = 0;
			    if (strchr(start+2, 'A'))
				    iauth_options |= XOPT_EARLYPARSE;
			    if (strchr(start+2, 'R'))
				    iauth_options |= XOPT_REQUIRED;
			    if (strchr(start+2, 'T'))
				    iauth_options |= XOPT_NOTIMEOUT;
			    if (strchr(start+2, 'W'))
				    iauth_options |= XOPT_EXTWAIT;
			    if (iauth_options)
				    sendto_flag(SCH_AUTH, "iauth options: %x",
						iauth_options);
			    start = end;
			    continue;
			}
		    if (*start == 'V') /* version */
			{
			    if (iauth_version)
				    MyFree(iauth_version);
			    iauth_version = mystrdup(start+2);
			    sendto_flag(SCH_AUTH, "iauth version %s running.",
					iauth_version);
			    start = end;
			    sendto_iauth("0 M %s", me.name);
			    continue;
			}
		    if (*start == 'a')
			{
			    aExtCf *ectmp;

			    while ((ectmp = iauth_conf))
				{
				    iauth_conf = iauth_conf->next;
				    MyFree(ectmp->line);
				    MyFree(ectmp);
				}
			    /* little lie.. ;) */
			    sendto_flag(SCH_AUTH, "New iauth configuration.");
			    start = end;
			    continue;
			}
		    if (*start == 'A')
			{
			    aExtCf **ectmp = &iauth_conf;

			    while (*ectmp)
				    ectmp = &((*ectmp)->next);
			    *ectmp = (aExtCf *) MyMalloc(sizeof(aExtCf));
			    (*ectmp)->line = mystrdup(start+2);
			    (*ectmp)->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start == 's')
			{
			    aExtData *ectmp;

			    while ((ectmp = iauth_stats))
				{
				    iauth_stats = iauth_stats->next;
				    MyFree(ectmp->line);
				    MyFree(ectmp);
				}
			    iauth_stats = (aExtData *)
				    MyMalloc(sizeof(aExtData));
			    iauth_stats->line = MyMalloc(60);
			    sprintf(iauth_stats->line,
				    "iauth modules statistics (%s)",
				    myctime(timeofday));
			    iauth_stats->next = (aExtData *)
				    MyMalloc(sizeof(aExtData));
			    iauth_stats->next->line = MyMalloc(60);
			    sprintf(iauth_stats->next->line,
				    "spawned: %d, current options: %X (%.11s)",
				    iauth_spawn, iauth_options,
				    (iauth_version) ? iauth_version : "???");
			    iauth_stats->next->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start == 'S')
			{
			    aExtData **ectmp = &iauth_stats;

			    while (*ectmp)
				    ectmp = &((*ectmp)->next);
			    *ectmp = (aExtData *) MyMalloc(sizeof(aExtData));
			    (*ectmp)->line = mystrdup(start+2);
			    (*ectmp)->next = NULL;
			    start = end;
			    continue;
			}
		    if (*start != 'U' && *start != 'u' && *start != 'o' &&
			*start != 'K' && *start != 'k' &&
			*start != 'D')
			{
			    sendto_flag(SCH_AUTH, "Garbage from iauth [%s]",
					start);
			    sendto_iauth("-1 E Garbage [%s]", start);
			    /*
			    ** The above should never happen, but i've seen it
			    ** occasionnally, so let's try to get more info
			    ** about it! -kalt
			    */
			    sendto_flag(SCH_AUTH,
				"last=%u start=%x end=%x buf=%x olen=%d i=%d",
					last, start, end, buf, olen, i);
			    sendto_iauth(
			 "-1 E last=%u start=%x end=%x buf=%x olen=%d i=%d",
			 		last, start, end, buf, olen, i);
			    start = end;
			    continue;
			}
		    if ((cptr = local[i = atoi(start+2)]) == NULL)
			{
			    /* this is fairly common and can be ignored */
			    if (ia_dbg)
				{
				    sendto_flag(SCH_AUTH, "Client %d is gone.",
						i);
				    sendto_iauth("%d E Gone [%s]", i, start);
				}
			    start = end;
			    continue;
			}
#ifndef	INET6
		    sprintf(tbuf, "%c %d %s %u ", start[0], i,
			    inetntoa((char *)&cptr->ip), cptr->port);
#else
		    sprintf(tbuf, "%c %d %s %u ", start[0], i,
			    inetntop(AF_INET6, (char *)&cptr->ip, 
			    ipv6string, sizeof(ipv6string)), cptr->port);
#endif
		    if (strncmp(tbuf, start, strlen(tbuf)))
			{
			    /* this is fairly common and can be ignored */
			    if (ia_dbg)
				{
				    sendto_flag(SCH_AUTH,
					"Client mismatch: %d [%s] != [%s]",
						i, start, tbuf);
				    sendto_iauth("%d E Mismatch [%s] != [%s]",
						 i, start, tbuf);
				}
			    start = end;
			    continue;
			}
		    if (start[0] == 'U')
			{
			    if (*(start+strlen(tbuf)) == '\0')
				{
				    sendto_flag(SCH_AUTH,
						"Null U message! %d [%s]",
						i, start);
				    sendto_iauth("%d E Null U [%s]", i, start);
				    start = end;
				    continue;
				}
			    if (cptr->auth != cptr->username)
				{   
				    istat.is_authmem -= strlen(cptr->auth) + 1;
				    istat.is_auth -= 1;
				    MyFree(cptr->auth);
				}
			    cptr->auth = mystrdup(start+strlen(tbuf));
			    set_clean_username(cptr);
			    cptr->flags |= FLAGS_GOTID;
			}
		    else if (start[0] == 'u')
			{
			    if (*(start+strlen(tbuf)) == '\0')
				{
				    sendto_flag(SCH_AUTH,
						"Null u message! %d [%s]",
						i, start);
				    sendto_iauth("%d E Null u [%s]", i, start);
				    start = end;
				    continue;
				}
			    if (cptr->auth != cptr->username)
				{
				    istat.is_authmem -= strlen(cptr->auth) + 1;
				    istat.is_auth -= 1;
				    MyFree(cptr->auth);
				}
			    cptr->auth = MyMalloc(strlen(start+strlen(tbuf))
						  + 2);
			    *cptr->auth = '-';
			    strcpy(cptr->auth+1, start+strlen(tbuf));
			    set_clean_username(cptr);
			    cptr->flags |= FLAGS_GOTID;
			}
		    else if (start[0] == 'o')
			{
			    if (!WaitingXAuth(cptr))
				{
				    sendto_flag(SCH_AUTH,
						"Early o message discarded!");
				    sendto_iauth("%d E Early o [%s]", i,start);
				    start = end;
				    continue;
				}
			    if (cptr->user == NULL)
				{
				    /* just to be safe */
				    sendto_flag(SCH_AUTH,
						"Ack! cptr->user is NULL");
				    start = end;
				    continue;
				}
			    strncpyzt(cptr->user->username, tbuf, USERLEN+1);
			}
		    else if (start[0] == 'D')
		      {
			    /*authentication finished*/
			    ClearXAuth(cptr);
			    SetDoneXAuth(cptr);
			    if (WaitingXAuth(cptr))
				{
				    ClearWXAuth(cptr);
				    register_user(cptr, cptr, cptr->name,
						  cptr->user->username);
				}
			    else
				    ClearWXAuth(cptr);
		      }
		    else
			{
			    char *reason;

			    /* Copy kill reason received from iauth */
			    reason = strstr(start, " :");
			    if (reason && (reason + 2 != '\0'))
			    {
				    if (cptr->reason)
				    {
					    MyFree(cptr->reason);
				    }
				    cptr->reason = mystrdup(reason + 2);
			    }
			    /*
			    ** mark for kill, because it cannot be killed
			    ** yet: we don't even know if this is a server
			    ** or a user connection!
			    */
			    if (start[0] == 'K')
				    cptr->exitc = EXITC_AREF;
			    else
				    cptr->exitc = EXITC_AREFQ;
			    /* should also check to make sure it's still
			       an unregistered client.. */

			    /* Finally, working after registration. --B. */
			    if (IsRegisteredUser(cptr))
			    {
                        	if (cptr->exitc == EXITC_AREF)
				{
					sendto_flag(SCH_LOCAL,
                                		"Denied after connection "
						"from %s.",
						get_client_host(cptr));
				}
                        	(void) exit_client(cptr, cptr, &me,
					cptr->reason ? cptr->reason :
					"Denied access");
			    }
			}
		    start = end;
		}
	    olen -= start - buf;
	    if (olen)
		    memcpy(obuf, start, olen);
	}
}
예제 #16
0
/*
 * ms_svsnick()
 *
 *     parv[0] = sender prefix
 *     parv[1] = oldnick
 *     parv[2] = newnick
 */
static void ms_svsnick(struct Client *client_p, struct Client *source_p,
                       int parc, char *parv[])
{
	char     oldnick[NICKLEN];
	char     newnick[NICKLEN];
	struct   Client *oldnickname;
	struct   Client *newnickname;

	if (!IsServer(source_p))
		return;

	/* XXX BadPtr is needed */
	if(parc < 3 || BadPtr(parv[1]) || BadPtr(parv[2]))
	{
		sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
		           me.name, parv[0]);
		return;
	}

	/* terminate nick to NICKLEN */
	strlcpy(oldnick, parv[1], NICKLEN);
	strlcpy(newnick, parv[2], NICKLEN);

	if(!clean_nick_name(oldnick))
	{
		sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
		           me.name, parv[0], oldnick);
		return;
	}

	/* check the nickname is ok */
	if(!clean_nick_name(newnick))
	{
		sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
		           me.name, parv[0], newnick);
		return;
	}

	if(find_nick_resv(newnick) &&
	        !(IsOper(source_p) && ConfigChannel.oper_pass_resv))
	{
		sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
		           me.name, parv[0], newnick);
		return;
	}
	if(!(oldnickname = find_client(oldnick)))
	{
		sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, oldnick);
		return;
	}
	if(newnickname = find_client(newnick))
	{
		sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
		           parv[0], newnick);
		return;
	}
	if(MyConnect(oldnickname))
	{
		if(!IsFloodDone(oldnickname))
			flood_endgrace(oldnickname);
		if (newnickname = find_client(oldnick))
		{
			if(newnickname == oldnickname)
			{
				/* check the nick isnt exactly the same */
				if(strcmp(oldnickname->name, newnick))
				{
					change_local_nick(oldnickname->servptr, oldnickname, newnick);
					return;
				}
				else
				{
					/* client is doing :old NICK old
					* ignore it..
					*/
					return;
				}
			}
			/* if the client that has the nick isnt registered yet (nick but no
			 * user) then drop the unregged client
			 */
			if(IsUnknown(newnickname))
			{
				/* the old code had an if(MyConnect(target_p)) here.. but I cant see
				 * how that can happen, m_nick() is local only --fl_
				 */

				exit_client(NULL, newnickname, &me, "Overridden");
				change_local_nick(oldnickname->servptr, oldnickname, newnick);
				return;
			}
			else
			{
				sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
				           parv[0], newnick);
				return;
			}
		}
		else
		{
			if(!ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL))
			{
				/* The uplink might know someone by this name already. */
				sendto_one(uplink, ":%s NBURST %s %s %s", me.name, newnick,
				           newnick, oldnickname->name);
				return;
			}
			else
			{
				change_local_nick(oldnickname->servptr, oldnickname, newnick);
				return;
			}
		}
	}
	else
	{
		sendto_server(client_p, source_p, NULL, CAP_SVNICK, NOCAPS, NOFLAGS,
		              ":%s SVSNICK %s %s", me.name, oldnick, newnick);
		return;
	}
}
예제 #17
0
파일: s_bsd.c 프로젝트: mojadita/ircd
/** Attempt to send a sequence of bytes to the connection.
 * As a side effect, updates \a cptr's FLAG_BLOCKED setting
 * and sendB/sendK fields.
 * @param cptr Client that should receive data.
 * @param buf Message buffer to send to client.
 * @return Negative on connection-fatal error; otherwise
 *  number of bytes sent.
 */
unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
{
  unsigned int bytes_written = 0;
  unsigned int bytes_count = 0;
  assert(0 != cptr);

#if defined(USE_SSL)
  switch (client_sendv(cptr, buf, &bytes_count, &bytes_written)) {
#else
  switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) {
#endif
  case IO_SUCCESS:
    ClrFlag(cptr, FLAG_BLOCKED);

    cli_sendB(cptr) += bytes_written;
    cli_sendB(&me)  += bytes_written;
    /* A partial write implies that future writes will block. */
    if (bytes_written < bytes_count)
      SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_BLOCKED:
    SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_FAILURE:
    cli_error(cptr) = errno;
    SetFlag(cptr, FLAG_DEADSOCKET);
    break;
  }
  return bytes_written;
}

/** Complete non-blocking connect()-sequence. Check access and
 * terminate connection, if trouble detected.
 * @param cptr Client to which we have connected, with all ConfItem structs attached.
 * @return Zero on failure (caller should exit_client()), non-zero on success.
 */
static int completed_connection(struct Client* cptr)
{
  struct ConfItem *aconf;
  time_t newts;
  struct Client *acptr;
  int i;
#if defined(USE_SSL)
  char *sslfp;
  int r;
#endif

  assert(0 != cptr);

  /*
   * get the socket status from the fd first to check if
   * connection actually succeeded
   */
  if ((cli_error(cptr) = os_get_sockerr(cli_fd(cptr)))) {
    const char* msg = strerror(cli_error(cptr));
    if (!msg)
      msg = "Unknown error";
    sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: %s",
                  cli_name(cptr), msg);
    return 0;
  }
  if (!(aconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_SERVER))) {
    sendto_opmask(0, SNO_OLDSNO, "Lost Server Line for %s", cli_name(cptr));
    return 0;
  }

#if defined(USE_SSL)
  if (aconf->flags & CONF_SSL) {
    r = ssl_connect(&(cli_socket(cptr)));
    if (r == -1) {
      sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: SSL error",
                    cli_name(cptr));
      return 0;
    } else if (r == 0)
      return 1;
    sslfp = ssl_get_fingerprint(cli_socket(cptr).s_ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(cptr), sslfp, BUFSIZE+1);
    SetSSL(cptr);
  }
#endif

  if (s_state(&(cli_socket(cptr))) == SS_CONNECTING)
    socket_state(&(cli_socket(cptr)), SS_CONNECTED);

  if (!EmptyString(aconf->passwd))
    sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);

  /*
   * Create a unique timestamp
   */
  newts = TStime();
  for (i = HighestFd; i > -1; --i) {
    if ((acptr = LocalClientArray[i]) &&
        (IsServer(acptr) || IsHandshake(acptr))) {
      if (cli_serv(acptr)->timestamp >= newts)
        newts = cli_serv(acptr)->timestamp + 1;
    }
  }
  assert(0 != cli_serv(cptr));

  cli_serv(cptr)->timestamp = newts;
  SetHandshake(cptr);
  /*
   * Make us timeout after twice the timeout for DNS look ups
   */
  cli_lasttime(cptr) = CurrentTime;
  ClearPingSent(cptr);

/* TODO: NEGOCIACION
  envia_config_req(cptr);
*/

  sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
                cli_name(&me), cli_serv(&me)->timestamp, newts,
		MAJOR_PROTOCOL, NumServCap(&me),
		feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));

#if defined(DDB)
  ddb_burst(cptr);
#endif

  return (IsDead(cptr)) ? 0 : 1;
}

/** Close the physical connection.  Side effects: MyConnect(cptr)
 * becomes false and cptr->from becomes NULL.
 * @param cptr Client to disconnect.
 */
void close_connection(struct Client *cptr)
{
  struct ConfItem* aconf;

  if (IsServer(cptr)) {
    ServerStats->is_sv++;
    ServerStats->is_sbs += cli_sendB(cptr);
    ServerStats->is_sbr += cli_receiveB(cptr);
    ServerStats->is_sti += CurrentTime - cli_firsttime(cptr);
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf->hold = CurrentTime;
      aconf->hold += ((aconf->hold - cli_since(cptr) >
		       feature_int(FEAT_HANGONGOODLINK)) ?
		      feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf));
/*        if (nextconnect > aconf->hold) */
/*          nextconnect = aconf->hold; */
    }
  }
  else if (IsUser(cptr)) {
    ServerStats->is_cl++;
    ServerStats->is_cbs += cli_sendB(cptr);
    ServerStats->is_cbr += cli_receiveB(cptr);
    ServerStats->is_cti += CurrentTime - cli_firsttime(cptr);
  }
  else
    ServerStats->is_ni++;

#if defined(USE_ZLIB)
  /*
   * Siempre es una conexion nuestra
   */
  if (cli_connect(cptr)->zlib_negociation & ZLIB_IN) {
    inflateEnd(cli_connect(cptr)->comp_in);
    MyFree(cli_connect(cptr)->comp_in);
  }
  if (cli_connect(cptr)->zlib_negociation & ZLIB_OUT) {
    deflateEnd(cli_connect(cptr)->comp_out);
    MyFree(cli_connect(cptr)->comp_out);
  }
#endif

  if (-1 < cli_fd(cptr)) {
    flush_connections(cptr);
    LocalClientArray[cli_fd(cptr)] = 0;
    close(cli_fd(cptr));
    socket_del(&(cli_socket(cptr))); /* queue a socket delete */
    cli_fd(cptr) = -1;
    cli_freeflag(cptr) &= ~FREEFLAG_SOCKET;
  }
  SetFlag(cptr, FLAG_DEADSOCKET);

  MsgQClear(&(cli_sendQ(cptr)));
  client_drop_sendq(cli_connect(cptr));
  DBufClear(&(cli_recvQ(cptr)));
  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
  set_snomask(cptr, 0, SNO_SET);

  det_confs_butmask(cptr, 0);

  if (cli_listener(cptr)) {
    release_listener(cli_listener(cptr));
    cli_listener(cptr) = 0;
  }

  for ( ; HighestFd > 0; --HighestFd) {
    if (LocalClientArray[HighestFd])
      break;
  }
}

/** Close all unregistered connections.
 * @param source Oper who requested the close.
 * @return Number of closed connections.
 */
int net_close_unregistered_connections(struct Client* source)
{
  int            i;
  struct Client* cptr;
  int            count = 0;
  assert(0 != source);

  for (i = HighestFd; i > 0; --i) {
    if ((cptr = LocalClientArray[i]) && !IsRegistered(cptr)) {
      send_reply(source, RPL_CLOSING, get_client_name(source, HIDE_IP));
      exit_client(source, cptr, &me, "Oper Closing");
      ++count;
    }
  }
  return count;
}
예제 #18
0
파일: s_bsd.c 프로젝트: Niichan/snircd
/** Read a 'packet' of data from a connection and process it.  Read in
 * 8k chunks to give a better performance rating (for server
 * connections).  Do some tricky stuff for client connections to make
 * sure they don't do any flooding >:-) -avalon
 * @param cptr Client from which to read data.
 * @param socket_ready If non-zero, more data can be read from the client's socket.
 * @return Positive number on success, zero on connection-fatal failure, negative
 *   if user is killed.
 */
static int read_packet(struct Client *cptr, int socket_ready)
{
  unsigned int dolen = 0;
  unsigned int length = 0;

  if (socket_ready &&
      !(IsUser(cptr) && !IsOper(cptr) &&
	DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))) {
    switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) {
    case IO_SUCCESS:
      if (length)
      {
        cli_lasttime(cptr) = CurrentTime;
        ClearPingSent(cptr);
        ClrFlag(cptr, FLAG_NONL);
        if (cli_lasttime(cptr) > cli_since(cptr))
          cli_since(cptr) = cli_lasttime(cptr);
      }
      break;
    case IO_BLOCKED:
      break;
    case IO_FAILURE:
      cli_error(cptr) = errno;
      /* SetFlag(cptr, FLAG_DEADSOCKET); */
      return 0;
    }
  }

  /*
   * For server connections, we process as many as we can without
   * worrying about the time of day or anything :)
   */
  if (length > 0 && IsServer(cptr))
    return server_dopacket(cptr, readbuf, length);
  else if (length > 0 && (IsHandshake(cptr) || IsConnecting(cptr)))
    return connect_dopacket(cptr, readbuf, length);
  else
  {
    /*
     * Before we even think of parsing what we just read, stick
     * it on the end of the receive queue and do it when its
     * turn comes around.
     */
    if (length > 0 && dbuf_put(&(cli_recvQ(cptr)), readbuf, length) == 0)
      return exit_client(cptr, cptr, &me, "dbuf_put fail");

    if (IsUser(cptr)) {
      if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD)
	&& !IsOper(cptr))
      return exit_client(cptr, cptr, &me, "Excess Flood");
    }

    while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && 
           (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10))
    {
      dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE);
      /*
       * Devious looking...whats it do ? well..if a client
       * sends a *long* message without any CR or LF, then
       * dbuf_getmsg fails and we pull it out using this
       * loop which just gets the next 512 bytes and then
       * deletes the rest of the buffer contents.
       * -avalon
       */
      if (dolen == 0)
      {
        if (DBufLength(&(cli_recvQ(cptr))) < 510)
          SetFlag(cptr, FLAG_NONL);
        else
        {
          /* More than 512 bytes in the line - drop the input and yell
           * at the client.
           */
          DBufClear(&(cli_recvQ(cptr)));
          send_reply(cptr, ERR_INPUTTOOLONG);
        }
      }
      else if (client_dopacket(cptr, dolen) == CPTR_KILLED)
        return CPTR_KILLED;
      /*
       * If it has become registered as a Server
       * then skip the per-message parsing below.
       */
      if (IsHandshake(cptr) || IsServer(cptr))
      {
        while (-1)
        {
          dolen = dbuf_get(&(cli_recvQ(cptr)), readbuf, sizeof(readbuf));
          if (dolen <= 0)
            return 1;
          else if (dolen == 0)
          {
            if (DBufLength(&(cli_recvQ(cptr))) < 510)
              SetFlag(cptr, FLAG_NONL);
            else
              DBufClear(&(cli_recvQ(cptr)));
          }
          else if ((IsServer(cptr) &&
                    server_dopacket(cptr, readbuf, dolen) == CPTR_KILLED) ||
                   (!IsServer(cptr) &&
                    connect_dopacket(cptr, readbuf, dolen) == CPTR_KILLED))
            return CPTR_KILLED;
        }
      }
    }

    /* If there's still data to process, wait 2 seconds first */
    if (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) &&
	!t_onqueue(&(cli_proc(cptr))))
    {
      Debug((DEBUG_LIST, "Adding client process timer for %C", cptr));
      cli_freeflag(cptr) |= FREEFLAG_TIMER;
      timer_add(&(cli_proc(cptr)), client_timer_callback, cli_connect(cptr),
		TT_RELATIVE, 2);
    }
  }
  return 1;
}