Esempio n. 1
0
void
scache_split(struct scache_entry *ptr)
{
	if (ptr == NULL)
		return;
	ptr->flags &= ~SC_ONLINE;
	ptr->last_split = rb_current_time();
}
Esempio n. 2
0
static int
m_cycle(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    char *p, *name;
    char *s = LOCAL_COPY(parv[1]);
    struct Channel *chptr;
    struct membership *msptr;

    name = rb_strtok_r(s, ",", &p);

    /* Finish the flood grace period... */
    if(MyClient(source_p) && !IsFloodDone(source_p))
        flood_endgrace(source_p);

    while(name) {
        if((chptr = find_channel(name)) == NULL) {
            sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
            return 0;
        }

        msptr = find_channel_membership(chptr, source_p);
        if(msptr == NULL) {
            sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name);
            return 0;
        }

        if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p))
            check_spambot_warning(source_p, NULL);

        if((is_any_op(msptr) || !MyConnect(source_p) ||
            ((can_send(chptr, source_p, msptr) > 0 &&
              (source_p->localClient->firsttime +
               ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time())))) {
            sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                          ":%s PART %s :Cycling", use_id(source_p), chptr->chname);
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :Cycling",
                                 source_p->name, source_p->username,
                                 source_p->host, chptr->chname);
        } else {
            sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                          ":%s PART %s", use_id(source_p), chptr->chname);
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
                                 source_p->name, source_p->username,
                                 source_p->host, chptr->chname);
        }

        remove_user_from_channel(msptr);

        chptr = NULL;
        msptr = NULL;

        name = rb_strtok_r(NULL, ",", &p);
    }

    user_join(client_p, source_p, parv[1], parc > 2 ? parv[2] : NULL);

    return 0;
}
Esempio n. 3
0
/*
 * mr_admin - ADMIN command handler
 *      parv[1] = servername
 */
static int
mr_admin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    static time_t last_used = 0L;

    if((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) {
        sendto_one(source_p, form_str(RPL_LOAD2HI),
                   me.name,
                   EmptyString(source_p->name) ? "*" : source_p->name,
                   "ADMIN");
        return 0;
    } else
        last_used = rb_current_time();

    do_admin(source_p);

    return 0;
}
Esempio n. 4
0
/* m_mkpasswd - mkpasswd message handler
 *	parv[1] = password
 *	parv[2] = type
 */
static int
m_mkpasswd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    static time_t last_used = 0;
    char *salt;
    const char *hashtype;
    const char hashdefault[] = "SHA512";

    if(EmptyString(parv[1]))
    {
        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MKPASSWD");
        return 0;
    }

    if(parc < 3)
        hashtype = hashdefault;
    else
        hashtype = parv[2];

    if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
    {
        /* safe enough to give this on a local connect only */
        sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name, "MKPASSWD");
        return 0;
    }
    else
        last_used = rb_current_time();

    if(!irccmp(hashtype, "SHA256"))
        salt = make_sha256_salt(16);
    else if(!irccmp(hashtype, "SHA512"))
        salt = make_sha512_salt(16);
    else if(!irccmp(hashtype, "MD5"))
        salt = make_md5_salt(8);
    else
    {
        sendto_one_notice(source_p,
                          ":MKPASSWD syntax error:  MKPASSWD pass [SHA256|SHA512|MD5]");
        return 0;
    }

    sendto_one_notice(source_p, ":Hash [%s] for %s: %s", hashtype, parv[1], rb_crypt(parv[1], salt));
    return 0;
}
Esempio n. 5
0
/*
** m_motd
**      parv[1] = servername
*/
static int
m_motd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	static time_t last_used = 0;
	if ((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) {
		/* safe enough to give this on a local connect only */
		sendto_one(source_p, form_str(RPL_LOAD2HI),
		           me.name, source_p->name, "MOTD");
		sendto_one(source_p, form_str(RPL_ENDOFMOTD),
		           me.name, source_p->name);
		return 0;
	} else
		last_used = rb_current_time();
	if (hunt_server(client_p, source_p, ":%s MOTD :%s", 1, parc, parv) != HUNTED_ISME)
		return 0;
	motd_spy(source_p);
	send_user_motd(source_p);
	return 0;
}
Esempio n. 6
0
/*
 * part_one_client
 *
 * inputs	- pointer to server
 * 		- pointer to source client to remove
 *		- char pointer of name of channel to remove from
 * output	- none
 * side effects	- remove ONE client given the channel name
 */
static void
part_one_client(struct Client *client_p, struct Client *source_p, char *name, char *reason)
{
    struct Channel *chptr;
    struct membership *msptr;
    char reason2[BUFSIZE];

    if((chptr = find_channel(name)) == NULL)
    {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
        return;
    }

    msptr = find_channel_membership(chptr, source_p);
    if(msptr == NULL)
    {
        sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name);
        return;
    }

    if(MyConnect(source_p) && !IsOper(source_p) && !IsExemptSpambot(source_p))
        check_spambot_warning(source_p, NULL);

    /*
     *  Remove user from the old channel (if any)
     *  only allow /part reasons in -m chans
     */
    if(reason[0] && (is_chanop(msptr) || !MyConnect(source_p) ||
                     ((can_send(chptr, source_p, msptr) > 0 &&
                       (source_p->localClient->firsttime +
                        ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time()))))
    {
        if(chptr->mode.mode & MODE_NOCOLOR)
        {
            rb_strlcpy(reason2, reason, BUFSIZE);
            strip_colour(reason2);
            reason = reason2;
        }
        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s PART %s :%s", use_id(source_p), chptr->chname, reason);
        sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
                             source_p->name, source_p->username,
                             source_p->host, chptr->chname, reason);
    }
    else
    {
        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s PART %s", use_id(source_p), chptr->chname);
        sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
                             source_p->name, source_p->username,
                             source_p->host, chptr->chname);
    }
    remove_user_from_channel(msptr);
}
Esempio n. 7
0
static void
rb_ssl_info_callback(SSL * ssl, int where, int ret)
{
	if(where & SSL_CB_HANDSHAKE_START)
	{
		rb_fde_t *F = SSL_get_ex_data(ssl, libratbox_index);
		if(F == NULL)
			return;
		F->handshake_count++;
		F->last_handshake = rb_current_time();
	}
}
Esempio n. 8
0
/*
 * m_admin - ADMIN command handler
 *      parv[1] = servername
 */
static int
m_admin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    static time_t last_used = 0L;

    if(parc > 1) {
        if((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) {
            sendto_one(source_p, form_str(RPL_LOAD2HI),
                       me.name, source_p->name, "ADMIN");
            return 0;
        } else
            last_used = rb_current_time();

        if(hunt_server(client_p, source_p, ":%s ADMIN :%s", 1, parc, parv) != HUNTED_ISME)
            return 0;
    }

    do_admin(source_p);

    return 0;
}
Esempio n. 9
0
/*
 * m_version - VERSION command handler
 *      parv[1] = remote server
 */
static int
m_version(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	static time_t last_used = 0L;
	if (parc > 1) {
		if ((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) {
			/* safe enough to give this on a local connect only */
			sendto_one(source_p, form_str(RPL_LOAD2HI),
			           me.name, source_p->name, "VERSION");
			return 0;
		} else
			last_used = rb_current_time();
		if (hunt_server(client_p, source_p, ":%s VERSION :%s", 1, parc, parv) != HUNTED_ISME)
			return 0;
	}
	sendto_one_numeric(source_p, RPL_VERSION, form_str(RPL_VERSION),
	                   ircd_version, serno,
	                   me.name, confopts(source_p), TS_CURRENT,
	                   ServerInfo.sid);
	show_isupport(source_p);
	return 0;
}
Esempio n. 10
0
struct scache_entry *
scache_connect(const char *name, const char *info, int hidden)
{
	struct scache_entry *ptr;

	ptr = find_or_add(name);
	rb_strlcpy(ptr->info, info, sizeof(ptr->info));
	ptr->flags |= SC_ONLINE;
	if (hidden)
		ptr->flags |= SC_HIDDEN;
	else
		ptr->flags &= ~SC_HIDDEN;
	ptr->last_connect = rb_current_time();
	return ptr;
}
Esempio n. 11
0
/*
 * m_time
 *      parv[0] = sender prefix
 *      parv[1] = servername
 */
static int
m_time(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    /* this is not rate limited, so end the grace period */
    char buf[80];
    if (MyClient(source_p) && !IsFloodDone(source_p))
        flood_endgrace(source_p);


    if (hunt_server(client_p, source_p, ":%s TIME :%s", 1, parc, parv) == HUNTED_ISME)
    {
        sendto_one_numeric(source_p, RPL_TIME, form_str(RPL_TIME),
                           me.name, rb_date(rb_current_time(), buf, sizeof(buf)));
    }
    return 0;
}
Esempio n. 12
0
struct Client *get_history(const char *nick, time_t timelimit)
{
	struct Whowas *temp;
	int blah;
	timelimit = rb_current_time() - timelimit;
	blah = hash_whowas_name(nick);
	temp = WHOWASHASH[blah];
	for (; temp; temp = temp->next) {
		if (irccmp(nick, temp->name))
			continue;
		if (temp->logoff < timelimit)
			continue;
		return temp->online;
	}
	return NULL;
}
Esempio n. 13
0
/*
** ms_eob
**      parv[0] = sender prefix
**      parv[1] = opt. comma separated list of SIDs for which this EOB is
**                also valid
*/
static int
ms_eob(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	char *copy, *state, *id;
	struct Client *target_p;
	int act = 0;

	if(!HasSentEob(source_p))
	{
		if(MyConnect(source_p))
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "End of burst from %s (%d seconds)",
					     source_p->name,
					     (signed int)(rb_current_time() -
							  source_p->localClient->firsttime));
			sendto_one(source_p, ":%s EOBACK", me.id);
		}
		act = 1;
		SetEob(source_p);
		eob_count++;
	}
	if(parc > 1 && *parv[1] != '\0')
	{
		copy = LOCAL_COPY(parv[1]);
		for(id = rb_strtok_r(copy, ",", &state); id != NULL;
				id = rb_strtok_r(NULL, ",", &state))
		{
			target_p = find_id(id);
			if(target_p != NULL && IsServer(target_p) &&
					target_p->from == client_p &&
					!HasSentEob(target_p))
			{
				SetEob(target_p);
				eob_count++;
				act = 1;
			}
		}
	}
	if(!act)
		return 0;
	sendto_server(client_p, NULL, CAP_IRCNET, NOCAPS, ":%s EOB%s%s",
			source_p->id,
			parc > 1 ? " :" : "", parc > 1 ? parv[1] : "");

	return 0;
}
Esempio n. 14
0
void
add_history(struct Client *client_p, int online)
{
	struct Whowas *who = &WHOWAS[whowas_next];

	s_assert(NULL != client_p);

	if(client_p == NULL)
		return;

	if(who->hashv != -1)
	{
		if(who->online)
			del_whowas_from_clist(&(who->online->whowas), who);
		del_whowas_from_list(&WHOWASHASH[who->hashv], who);
	}
	who->hashv = hash_whowas_name(client_p->name);
	who->logoff = rb_current_time();
	/*
	 * NOTE: strcpy ok here, the sizes in the client struct MUST
	 * match the sizes in the whowas struct
	 */
	rb_strlcpy(who->name, client_p->name, sizeof(who->name));
	strcpy(who->username, client_p->username);
	strcpy(who->hostname, client_p->host);
	strcpy(who->realname, client_p->info);
	strcpy(who->suser, client_p->user->suser);
	if(!EmptyString(client_p->sockhost) && strcmp(client_p->sockhost, "0")
	   && show_ip(NULL, client_p))
		strcpy(who->sockhost, client_p->sockhost);
	else
		who->sockhost[0] = '\0';

	who->servername = scache_get_name(client_p->servptr->serv->nameinfo);

	if(online)
	{
		who->online = client_p;
		add_whowas_to_clist(&(client_p->whowas), who);
	}
	else
		who->online = NULL;
	add_whowas_to_list(&WHOWASHASH[who->hashv], who);
	whowas_next++;
	if(whowas_next == NICKNAMEHISTORYLENGTH)
		whowas_next = 0;
}
Esempio n. 15
0
static int
ms_pong(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	const char *destination;

	destination = parv[2];
	source_p->flags &= ~FLAGS_PINGSENT;

	/* Now attempt to route the PONG, comstud pointed out routable PING
	 * is used for SPING.  routable PING should also probably be left in
	 *        -Dianora
	 * That being the case, we will route, but only for registered clients (a
	 * case can be made to allow them only from servers). -Shadowfax
	 */
	if(!EmptyString(destination) && !match(destination, me.name) &&
	   irccmp(destination, me.id))
	{
		if((target_p = find_client(destination)))
			sendto_one(target_p, ":%s PONG %s %s", 
				   get_id(source_p, target_p), parv[1], 
				   get_id(target_p, target_p));
		else
		{
			if(!IsDigit(*destination))
				sendto_one_numeric(source_p, ERR_NOSUCHSERVER,
						   form_str(ERR_NOSUCHSERVER), destination);
			return 0;
		}
	}

	/* destination is us, emulate EOB */
	if(IsServer(source_p) && !HasSentEob(source_p))
	{
		if(MyConnect(source_p))
			sendto_realops_snomask(SNO_GENERAL, L_ALL,
					     "End of burst (emulated) from %s (%d seconds)",
					     source_p->name,
					     (signed int) (rb_current_time() - source_p->localClient->firsttime));
		SetEob(source_p);
		eob_count++;
		call_hook(h_server_eob, source_p);
	}

	return 0;
}
Esempio n. 16
0
static int
mo_testgecos(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct ConfItem *aconf;

    if(!(aconf = find_xline(parv[1], 0))) {
        sendto_one(source_p, form_str(RPL_NOTESTLINE),
                   me.name, source_p->name, parv[1]);
        return 0;
    }

    sendto_one(source_p, form_str(RPL_TESTLINE),
               me.name, source_p->name,
               aconf->hold ? 'x' : 'X',
               aconf->hold ? (long) ((aconf->hold - rb_current_time()) / 60) : 0L,
               aconf->host, aconf->passwd);
    return 0;
}
Esempio n. 17
0
static int
mo_testgecos(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;

	if(!(aconf = find_xline(parv[1], 0)))
	{
		sendto_one_numeric(source_p, s_RPL(RPL_NOTESTLINE), parv[1]);
		return 0;
	}

	sendto_one_numeric(source_p, s_RPL(RPL_TESTLINE),
		   (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'x' : 'X',
		   (aconf->flags & CONF_FLAGS_TEMPORARY) ? (time_t)((aconf->hold -
							     rb_current_time()) / 60) : (time_t)0L,
		   aconf->host, aconf->passwd);
	return 0;
}
Esempio n. 18
0
/* scache_send_missing()
 *
 * inputs	- client to send to
 * outputs	- recently split servers
 * side effects	-
 */
void
scache_send_missing(struct Client *source_p)
{
	struct scache_entry *scache_ptr;
	int i;

	for (i = 0; i < SCACHE_HASH_SIZE; i++)
	{
		scache_ptr = scache_hash[i];
		while (scache_ptr)
		{
			if (!(scache_ptr->flags & SC_ONLINE) && scache_ptr->last_split > rb_current_time() - MISSING_TIMEOUT)
				sendto_one_numeric(source_p, RPL_MAP, "** %s (recently split)", 
						   scache_ptr->name);

			scache_ptr = scache_ptr->next;
		}
	}
}
Esempio n. 19
0
void
add_history(struct Client *client_p, int online)
{
    struct Whowas *who = &WHOWAS[whowas_next];

    s_assert(NULL != client_p);

    if (client_p == NULL)
        return;

    if (who->hashv != -1)
    {
        if (who->online)
            del_whowas_from_clist(&(who->online->whowas), who);
        del_whowas_from_list(&WHOWASHASH[who->hashv], who);
    }
    who->hashv = hash_whowas_name(client_p->name);
    who->logoff = rb_current_time();

    strcpy(who->name, client_p->name);
    strcpy(who->username, client_p->username);
    strcpy(who->hostname, client_p->host);
    strcpy(who->virthost, client_p->virthost);
    strcpy(who->realname, client_p->info);

    who->cloak = IsCloaked(client_p);

    who->servername = client_p->servptr->name;

    if (online)
    {
        who->online = client_p;
        add_whowas_to_clist(&(client_p->whowas), who);
    }
    else
        who->online = NULL;
    add_whowas_to_list(&WHOWASHASH[who->hashv], who);
    whowas_next++;
    if (whowas_next == NICKNAMEHISTORYLENGTH)
        whowas_next = 0;
}
Esempio n. 20
0
static void
log_va(const ilogfile dest, const unsigned int snomask, const char *const fmt, va_list ap)
{
	FILE *const logfile = *log_table[dest].logfile;
	if(!logfile && !snomask)
		return;

	char buf[BUFSIZE];
	vsnprintf(buf, sizeof(buf), fmt, ap);

	if(snomask)
		sendto_realops_snomask(snomask, L_ALL, "%s", buf);

	if(fprintf(logfile, "%s %s\n", smalldate(rb_current_time()), buf) < 0)
	{
		fclose(logfile);
		*log_table[dest].logfile = NULL;
	} else {
		fflush(logfile);
	}
}
Esempio n. 21
0
static int
change_nick(struct Client *client_p, const char *newnick)
{
	char note[NICKLEN + 10];

	client_p->tsinfo = rb_current_time();

	monitor_signoff(client_p);

	invalidate_bancache_user(client_p);

	sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
			"Forced nick change: From %s to %s [%s@%s]",
			client_p->name, newnick, client_p->username,
			client_p->host);

	sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s",
				client_p->name, client_p->username,
				client_p->host, newnick);

	add_history(client_p, 1);
	sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
			use_id(client_p), newnick, (long) client_p->tsinfo);

	del_from_client_hash(client_p->name, client_p);
	strcpy(client_p->name, newnick);
	add_to_client_hash(client_p->name, client_p);

	monitor_signon(client_p);

	del_all_accepts(client_p);

	rb_snprintf(note, NICKLEN + 10, "Nick: %s", client_p->name);
	rb_note(client_p->localClient->F, note);
	return 0;
}
Esempio n. 22
0
/* date()
 *
 * returns date in human readable form
 */
static char *
date(void)
{
    static char buf[80];
    char plus;
    struct tm *lt;
    struct tm *gm;
    struct tm gmbuf;
    time_t lclock;
    int minswest;

    lclock = rb_current_time();
    gm = gmtime(&lclock);
    memcpy((void *) &gmbuf, (void *) gm, sizeof(gmbuf));
    gm = &gmbuf;
    lt = localtime(&lclock);

    if(lt->tm_yday == gm->tm_yday)
        minswest = (gm->tm_hour - lt->tm_hour) * 60 + (gm->tm_min - lt->tm_min);
    else if(lt->tm_yday > gm->tm_yday && lt->tm_year == gm->tm_year)
        minswest = (gm->tm_hour - (lt->tm_hour + 24)) * 60;
    else
        minswest = ((gm->tm_hour + 24) - lt->tm_hour) * 60;

    plus = (minswest > 0) ? '-' : '+';

    if(minswest < 0)
        minswest = -minswest;

    sprintf(buf, "%s %s %d %d -- %02u:%02u:%02u %c%02u:%02u",
               weekdays[lt->tm_wday], months[lt->tm_mon], lt->tm_mday,
               lt->tm_year + 1900, lt->tm_hour, lt->tm_min, lt->tm_sec,
               plus, minswest / 60, minswest % 60);

    return buf;
}
Esempio n. 23
0
/*
** m_whowas
**      parv[1] = nickname queried
*/
static int
m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{	
	struct Whowas *temp;
	int cur = 0;
	int max = -1, found = 0;
	char *p;
	const char *nick;
	char tbuf[26];

	static time_t last_used = 0L;

	if(!IsOper(source_p))
	{
		if((last_used + ConfigFileEntry.pace_wait_simple) > rb_current_time())
		{
			sendto_one(source_p, form_str(RPL_LOAD2HI),
				   me.name, source_p->name, "WHOWAS");
			sendto_one(source_p, form_str(RPL_ENDOFWHOWAS),
				   me.name, source_p->name, parv[1]);
			return 0;
		}
		else
			last_used = rb_current_time();
	}


	if(parc > 2)
		max = atoi(parv[2]);

#if 0
	if(parc > 3)
		if(hunt_server(client_p, source_p, ":%s WHOWAS %s %s :%s", 3, parc, parv))
			return 0;
#endif

	if((p = strchr(parv[1], ',')))
		*p = '\0';

	nick = parv[1];

	temp = WHOWASHASH[hash_whowas_name(nick)];
	found = 0;
	for (; temp; temp = temp->next)
	{
		if(!irccmp(nick, temp->name))
		{
			sendto_one(source_p, form_str(RPL_WHOWASUSER),
				   me.name, source_p->name, temp->name,
				   temp->username, temp->hostname, temp->realname);
			if (MyOper(source_p) && !EmptyString(temp->sockhost))
#if 0
				sendto_one(source_p, form_str(RPL_WHOWASREAL),
					   me.name, source_p->name, temp->name,
					   "<untracked>", temp->sockhost);
#else
				sendto_one_numeric(source_p, RPL_WHOISACTUALLY,
						   form_str(RPL_WHOISACTUALLY),
						   temp->name, temp->sockhost);
#endif
			if (!EmptyString(temp->suser))
				sendto_one_numeric(source_p, RPL_WHOISLOGGEDIN,
						   "%s %s :was logged in as",
						   temp->name, temp->suser);
                        if(SeesServers(source_p))
			sendto_one_numeric(source_p, RPL_WHOISSERVER,
					   form_str(RPL_WHOISSERVER),
					   temp->name, temp->servername,
					   rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
			else
			sendto_one_numeric(source_p, RPL_WHOISSERVER,
					   form_str(RPL_WHOISSERVER),
					   temp->name, source_p->servptr->mname,
					   rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
			cur++;
			found++;
		}
		if(max > 0 && cur >= max)
			break;
	}

	if(!found)
		sendto_one(source_p, form_str(ERR_WASNOSUCHNICK), 
			   me.name, source_p->name, nick);

	sendto_one(source_p, form_str(RPL_ENDOFWHOWAS), 
		   me.name, source_p->name, parv[1]);
	return 0;
}
Esempio n. 24
0
static int
accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
{
	struct Listener *listener = (struct Listener *)data;
	char buf[BUFSIZE];
	struct ConfItem *aconf;
	static time_t last_oper_notice = 0;
	int len;

	if(listener->ssl && (!ssl_ok || !get_ssld_count()))
	{
		rb_close(F);
		return 0;
	}

	if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */
	{
		++ServerStats.is_ref;
		/*
		 * slow down the whining to opers bit
		 */
		if((last_oper_notice + 20) <= rb_current_time())
		{
			sendto_realops_snomask(SNO_GENERAL, L_ALL,
					     "All connections in use. (%s)",
					     get_listener_name(listener));
			last_oper_notice = rb_current_time();
		}
			
		rb_write(F, "ERROR :All connections in use\r\n", 32);
		rb_close(F);
		/* Re-register a new IO request for the next accept .. */
		return 0;
	}

	aconf = find_dline(addr, addr->sa_family);
	if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE))
		return 1;
	
	/* Do an initial check we aren't connecting too fast or with too many
	 * from this IP... */
	if(aconf != NULL)
	{
		ServerStats.is_ref++;
			
		if(ConfigFileEntry.dline_with_reason)
		{
			len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf));
			if (len >= (int)(sizeof(buf)-1))
			{
				buf[sizeof(buf) - 3] = '\r';
				buf[sizeof(buf) - 2] = '\n';
				buf[sizeof(buf) - 1] = '\0';
			}
		}
		else
			strcpy(buf, "ERROR :You have been D-lined.\r\n");
	
		rb_write(F, buf, strlen(buf));
		rb_close(F);
		return 0;
	}

	if(check_reject(F, addr))
		return 0;
		
	if(throttle_add(addr))
	{
		rb_write(F, toofast, strlen(toofast));
		rb_close(F);
		return 0;
	}

	return 1;
}
Esempio n. 25
0
/* ms_ban()
 *
 * parv[1] - type
 * parv[2] - username mask or *
 * parv[3] - hostname mask
 * parv[4] - creation TS
 * parv[5] - duration (relative to creation)
 * parv[6] - lifetime (relative to creation)
 * parv[7] - oper or *
 * parv[8] - reason (possibly with |operreason)
 */
static int
ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	rb_dlink_node *ptr;
	struct ConfItem *aconf;
	unsigned int ntype;
	const char *oper, *stype;
	time_t now, created, hold, lifetime;
	char *p;
	int act;
	int valid;

	now = rb_current_time();
	if (strlen(parv[1]) != 1)
	{
		sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
				"Unknown BAN type %s from %s",
				parv[1], source_p->name);
		return 0;
	}
	switch (parv[1][0])
	{
		case 'K':
			ntype = CONF_KILL;
			stype = "K-Line";
			break;
		case 'X':
			ntype = CONF_XLINE;
			stype = "X-Line";
			break;
		case 'R':
			ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL :
				CONF_RESV_NICK;
			stype = "RESV";
			break;
		default:
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"Unknown BAN type %s from %s",
					parv[1], source_p->name);
			return 0;
	}
	created = atol(parv[4]);
	hold = created + atoi(parv[5]);
	lifetime = created + atoi(parv[6]);
	if (!strcmp(parv[7], "*"))
		oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p);
	else
		oper = parv[7];
	ptr = find_prop_ban(ntype, parv[2], parv[3]);
	if (ptr != NULL)
	{
		/* We already know about this ban mask. */
		aconf = ptr->data;
		if (aconf->created > created ||
				(aconf->created == created &&
				 aconf->lifetime >= lifetime))
		{
			if (IsPerson(source_p))
				sendto_one_notice(source_p,
						":Your %s [%s%s%s] has been superseded",
						stype,
						aconf->user ? aconf->user : "",
						aconf->user ? "@" : "",
						aconf->host);
			return 0;
		}
		/* act indicates if something happened (from the oper's
		 * point of view). This is the case if the ban was
		 * previously active (not deleted) or if the new ban
		 * is not a removal and not already expired.
		 */
		act = !(aconf->status & CONF_ILLEGAL) || (hold != created &&
				hold > now);
		if (lifetime > aconf->lifetime)
			aconf->lifetime = lifetime;
		/* already expired, hmm */
		if (aconf->lifetime <= now)
			return 0;
		/* Deactivate, it will be reactivated later if appropriate. */
		deactivate_conf(aconf, ptr, now);
		rb_free(aconf->user);
		aconf->user = NULL;
		rb_free(aconf->host);
		aconf->host = NULL;
		operhash_delete(aconf->info.oper);
		aconf->info.oper = NULL;
		rb_free(aconf->passwd);
		aconf->passwd = NULL;
		rb_free(aconf->spasswd);
		aconf->spasswd = NULL;
	}
	else
	{
		/* New ban mask. */
		aconf = make_conf();
		aconf->status = CONF_ILLEGAL | ntype;
		aconf->lifetime = lifetime;
		rb_dlinkAddAlloc(aconf, &prop_bans);
		act = hold != created && hold > now;
	}
	aconf->flags &= ~CONF_FLAGS_MYOPER;
	aconf->flags |= CONF_FLAGS_TEMPORARY;
	aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL;
	aconf->host = rb_strdup(parv[3]);
	aconf->info.oper = operhash_add(oper);
	aconf->created = created;
	aconf->hold = hold;
	if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL)
		aconf->passwd = rb_strdup(parv[parc - 1]);
	else
	{
		aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1);
		aconf->spasswd = rb_strdup(p + 1);
	}
	/* The ban is fully filled in and in the prop_bans list
	 * but still deactivated. Now determine if it should be activated
	 * and send the server notices.
	 */
	/* We only reject *@* and the like here.
	 * Otherwise malformed bans are fairly harmless and can be removed.
	 */
	switch (ntype)
	{
		case CONF_KILL:
			valid = valid_wild_card(aconf->user, aconf->host);
			break;
		case CONF_RESV_CHANNEL:
			valid = 1;
			break;
		default:
			valid = valid_wild_card_simple(aconf->host);
			break;
	}
	if (act && hold != created && !valid)
	{
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				       "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters",
				       (int)((hold - now) / 60),
				       stype,
				       IsServer(source_p) ? source_p->name : get_oper_name(source_p),
				       strcmp(parv[7], "*") ? " on behalf of " : "",
				       strcmp(parv[7], "*") ? parv[7] : "",
				       aconf->user ? aconf->user : "",
				       aconf->user ? "@" : "",
				       aconf->host);
		if(IsPerson(source_p))
			sendto_one_notice(source_p,
					":Your %s [%s%s%s] has too few non-wildcard characters",
					stype,
					aconf->user ? aconf->user : "",
					aconf->user ? "@" : "",
					aconf->host);
		/* Propagate it, but do not apply it locally. */
	}
	else if (act && hold != created)
	{
		/* Keep the notices in sync with modules/m_kline.c etc. */
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				       "%s added global %d min. %s%s%s for [%s%s%s] [%s]",
				       IsServer(source_p) ? source_p->name : get_oper_name(source_p),
				       (int)((hold - now) / 60),
				       stype,
				       strcmp(parv[7], "*") ? " from " : "",
				       strcmp(parv[7], "*") ? parv[7] : "",
				       aconf->user ? aconf->user : "",
				       aconf->user ? "@" : "",
				       aconf->host,
				       parv[parc - 1]);
		ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1],
				IsServer(source_p) ? source_p->name : get_oper_name(source_p),
				(int)((hold - now) / 60),
				aconf->user ? aconf->user : "",
				aconf->user ? " " : "",
				aconf->host,
				parv[parc - 1]);
		aconf->status &= ~CONF_ILLEGAL;
	}
	else if (act)
	{
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"%s has removed the global %s for: [%s%s%s]%s%s",
				IsServer(source_p) ? source_p->name : get_oper_name(source_p),
				stype,
				aconf->user ? aconf->user : "",
				aconf->user ? "@" : "",
				aconf->host,
				strcmp(parv[7], "*") ? " on behalf of " : "",
				strcmp(parv[7], "*") ? parv[7] : "");
		ilog(L_KLINE, "U%s %s %s%s %s", parv[1],
				IsServer(source_p) ? source_p->name : get_oper_name(source_p),
				aconf->user ? aconf->user : "",
				aconf->user ? " " : "",
				aconf->host);
	}
	/* If CONF_ILLEGAL is still set at this point, remove entries from the
	 * reject cache (for klines and xlines).
	 * If CONF_ILLEGAL is not set, add the ban to the type-specific data
	 * structure and take action on matched clients/channels.
	 */
	switch (ntype)
	{
		case CONF_KILL:
			if (aconf->status & CONF_ILLEGAL)
				remove_reject_mask(aconf->user, aconf->host);
			else
			{
				add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
				if(ConfigFileEntry.kline_delay ||
						(IsServer(source_p) &&
						 !HasSentEob(source_p)))
				{
					if(kline_queued == 0)
					{
						rb_event_addonce("check_klines", check_klines_event, NULL,
							ConfigFileEntry.kline_delay ?
								ConfigFileEntry.kline_delay : 1);
						kline_queued = 1;
					}
				}
				else
					check_klines();
			}
			break;
		case CONF_XLINE:
			if (aconf->status & CONF_ILLEGAL)
				remove_reject_mask(aconf->host, NULL);
			else
			{
				rb_dlinkAddAlloc(aconf, &xline_conf_list);
				check_xlines();
			}
			break;
		case CONF_RESV_CHANNEL:
			if (!(aconf->status & CONF_ILLEGAL))
			{
				add_to_resv_hash(aconf->host, aconf);
				resv_chan_forcepart(aconf->host, aconf->passwd, hold - now);
			}
			break;
		case CONF_RESV_NICK:
			if (!(aconf->status & CONF_ILLEGAL))
				rb_dlinkAddAlloc(aconf, &resv_conf_list);
			break;
	}
	sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
			":%s BAN %s %s %s %s %s %s %s :%s",
			source_p->id,
			parv[1],
			parv[2],
			parv[3],
			parv[4],
			parv[5],
			parv[6],
			parv[7],
			parv[parc - 1]);
	return 0;
}
Esempio n. 26
0
static int
mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;
	struct ConfItem *resv_p;
	struct rb_sockaddr_storage ip;
	const char *name = NULL;
	const char *username = NULL;
	const char *host = NULL;
	char *mask;
	char *p;
	int host_mask;
	int type;

	mask = LOCAL_COPY(parv[1]);

	if(IsChannelName(mask))
	{
		resv_p = hash_find_resv(mask);
		if(resv_p != NULL)
		{
			sendto_one(source_p, form_str(RPL_TESTLINE),
				   me.name, source_p->name,
				   (resv_p->flags & CONF_FLAGS_TEMPORARY) ? 'q' : 'Q',
				   (resv_p->flags & CONF_FLAGS_TEMPORARY) ? (long)((resv_p->hold -
										    rb_current_time
										    ()) / 60) : 0L,
				   resv_p->host, resv_p->passwd);
			/* this is a false positive, so make sure it isn't counted in stats q
			 * --nenolod
			 */
			resv_p->port--;
		}
		else
			sendto_one(source_p, form_str(RPL_NOTESTLINE),
				   me.name, source_p->name, parv[1]);
		return 0;
	}

	if((p = strchr(mask, '!')))
	{
		*p++ = '\0';
		name = mask;
		mask = p;

		if(EmptyString(mask))
			return 0;
	}

	if((p = strchr(mask, '@')))
	{
		*p++ = '\0';
		username = mask;
		host = p;

		if(EmptyString(host))
			return 0;
	}
	else
		host = mask;

	/* parses as an IP, check for a dline */
	if((type = parse_netmask(host, (struct sockaddr *)&ip, &host_mask)) != HM_HOST)
	{
		aconf = find_dline((struct sockaddr *)&ip);

		if(aconf && aconf->status & CONF_DLINE)
		{
			sendto_one(source_p, form_str(RPL_TESTLINE),
				   me.name, source_p->name,
				   (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D',
				   (aconf->flags & CONF_FLAGS_TEMPORARY) ?
				   (long)((aconf->hold - rb_current_time()) / 60) : 0L,
				   aconf->host, aconf->passwd);

			return 0;
		}
	}

	/* now look for a matching I/K/G */
	if((aconf = find_address_conf(host, NULL, username ? username : "******",
				      (type != HM_HOST) ? (struct sockaddr *)&ip : NULL,
				      (type != HM_HOST) ? (
#ifdef RB_IPV6
										(type ==
										 HM_IPV6) ? AF_INET6
										:
#endif
										AF_INET) : 0)))
	{
		static char buf[HOSTLEN + USERLEN + 2];

		if(aconf->status & CONF_KILL)
		{
			rb_snprintf(buf, sizeof(buf), "%s@%s", aconf->user, aconf->host);
			sendto_one(source_p, form_str(RPL_TESTLINE),
				   me.name, source_p->name,
				   (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K',
				   (aconf->flags & CONF_FLAGS_TEMPORARY) ?
				   (long)((aconf->hold - rb_current_time()) / 60) : 0L,
				   buf, aconf->passwd);
			return 0;
		}
		else if(aconf->status & CONF_GLINE)
		{
			rb_snprintf(buf, sizeof(buf), "%s@%s", aconf->user, aconf->host);
			sendto_one(source_p, form_str(RPL_TESTLINE),
				   me.name, source_p->name,
				   'G', (long)((aconf->hold - rb_current_time()) / 60),
				   buf, aconf->passwd);
			return 0;
		}
	}

	/* they asked us to check a nick, so hunt for resvs.. */
	if(name && (resv_p = find_nick_resv(name)))
	{
		sendto_one(source_p, form_str(RPL_TESTLINE),
			   me.name, source_p->name,
			   (resv_p->flags & CONF_FLAGS_TEMPORARY) ? 'q' : 'Q',
			   (resv_p->flags & CONF_FLAGS_TEMPORARY) ? (long)((resv_p->hold -
									    rb_current_time()) /
									   60) : 0L, resv_p->host,
			   resv_p->passwd);

		/* this is a false positive, so make sure it isn't counted in stats q
		 * --nenolod
		 */
		resv_p->port--;
		return 0;
	}

	/* no matching resv, we can print the I: if it exists */
	if(aconf && aconf->status & CONF_CLIENT)
	{
		sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE),
				   aconf->info.name, show_iline_prefix(source_p, aconf,
								       aconf->user), aconf->host,
				   aconf->port, get_class_name(aconf));
		return 0;
	}

	/* nothing matches.. */
	sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]);
	return 0;
}
Esempio n. 27
0
/*
** m_away
**      parv[1] = away message
*/
static int
m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	if(MyClient(source_p) && source_p->localClient->next_away &&
			!IsFloodDone(source_p))
		flood_endgrace(source_p);

	if(!IsClient(source_p))
		return 0;

	if(parc < 2 || EmptyString(parv[1]))
	{
		/* Marking as not away */
		if(source_p->user->away != NULL)
		{
			/* we now send this only if they were away before --is */
			sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
				      ":%s AWAY", use_id(source_p));
			free_away(source_p);

			sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY",
							    source_p->name, source_p->username, source_p->host);
		}
		if(MyConnect(source_p))
			sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY));
		return 0;
	}

	/* Rate limit this because it is sent to common channels. */
	if (MyClient(source_p))
	{
		if(!IsOper(source_p) &&
				source_p->localClient->next_away > rb_current_time())
		{
			sendto_one(source_p, form_str(RPL_LOAD2HI),
					me.name, source_p->name, "AWAY");
			return 0;
		}
		if(source_p->localClient->next_away < rb_current_time() -
				ConfigFileEntry.away_interval)
			source_p->localClient->next_away = rb_current_time();
		else
			source_p->localClient->next_away = rb_current_time() +
				ConfigFileEntry.away_interval;
	}

	if(source_p->user->away == NULL)
		allocate_away(source_p);
	if(strncmp(source_p->user->away, parv[1], AWAYLEN - 1))
	{
		rb_strlcpy(source_p->user->away, parv[1], AWAYLEN);
		sendto_server(client_p, NULL, CAP_TS6, NOCAPS, 
			      ":%s AWAY :%s", use_id(source_p), source_p->user->away);
		sendto_common_channels_local_butone(source_p,
					            CLICAP_AWAY_NOTIFY,
						    ":%s!%s@%s AWAY :%s",
						    source_p->name,
						    source_p->username,
						    source_p->host,
						    source_p->user->away);
	}

	if(MyConnect(source_p))
		sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY));

	return 0;
}
Esempio n. 28
0
/* m_knock
 *    parv[1] = channel
 *
 *  The KNOCK command has the following syntax:
 *   :<sender> KNOCK <channel>
 *
 *  If a user is not banned from the channel they can use the KNOCK
 *  command to have the server NOTICE the channel operators notifying
 *  they would like to join.  Helpful if the channel is invite-only, the
 *  key is forgotten, or the channel is full (INVITE can bypass each one
 *  of these conditions.  Concept by Dianora <*****@*****.**> and written by
 *  <anonymous>
 */
static int
m_knock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;
    char *p, *name;

    if(MyClient(source_p) && ConfigChannel.use_knock == 0) {
        sendto_one(source_p, form_str(ERR_KNOCKDISABLED),
                   me.name, source_p->name);
        return 0;
    }

    name = LOCAL_COPY(parv[1]);

    /* dont allow one knock to multiple chans */
    if((p = strchr(name, ',')))
        *p = '\0';

    if(!IsChannelName(name)) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    if((chptr = find_channel(name)) == NULL) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    if(IsMember(source_p, chptr)) {
        if(MyClient(source_p))
            sendto_one(source_p, form_str(ERR_KNOCKONCHAN),
                       me.name, source_p->name, name);
        return 0;
    }

    if(!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) ||
         (chptr->mode.limit &&
          rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit))) {
        sendto_one_numeric(source_p, ERR_CHANOPEN,
                           form_str(ERR_CHANOPEN), name);
        return 0;
    }

    /* cant knock to a +p channel */
    if(HiddenChannel(chptr)) {
        sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                           form_str(ERR_CANNOTSENDTOCHAN), name, "channel does not accept knocks");
        return 0;
    }


    if(MyClient(source_p)) {
        /* don't allow a knock if the user is banned */
        if(is_banned(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN ||
           is_quieted(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN) {
            sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                               form_str(ERR_CANNOTSENDTOCHAN), name, "you are banned from this channel");
            return 0;
        }

        /* local flood protection:
         * allow one knock per user per knock_delay
         * allow one knock per channel per knock_delay_channel
         */
        if(!IsOper(source_p) &&
           (source_p->localClient->last_knock + ConfigChannel.knock_delay) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "user");
            return 0;
        } else if((chptr->last_knock + ConfigChannel.knock_delay_channel) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "channel");
            return 0;
        }

        /* ok, we actually can send the knock, tell client */
        source_p->localClient->last_knock = rb_current_time();

        sendto_one(source_p, form_str(RPL_KNOCKDLVR),
                   me.name, source_p->name, name);
    }

    chptr->last_knock = rb_current_time();

    if(ConfigChannel.use_knock)
        sendto_channel_local(chptr->mode.mode & MODE_FREEINVITE ? ALL_MEMBERS : ONLY_CHANOPS,
                             chptr, form_str(RPL_KNOCK),
                             me.name, name, name, source_p->name,
                             source_p->username, source_p->host);

    sendto_server(client_p, chptr, CAP_KNOCK|CAP_TS6, NOCAPS,
                  ":%s KNOCK %s", use_id(source_p), name);
    sendto_server(client_p, chptr, CAP_KNOCK, CAP_TS6,
                  ":%s KNOCK %s", source_p->name, name);
    return 0;
}
Esempio n. 29
0
/*
** mo_ojoin
**      parv[1] = channel
*/
static int
mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr;
	int move_me = 0;

	/* admins only */
	if(!IsOperAdmin(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return 0;
	}

	if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!'
	   || *parv[1] == '~')
	{
		parv[1]++;
		move_me = 1;
	}
	else
	{
		sendto_one_notice(source_p, ":Unrecognized op prefix '%c'", *parv[1]);
		return 0;
	}

	if((chptr = find_channel(parv[1])) == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	if(IsMember(source_p, chptr))
	{
		sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]);
		return 0;
	}

	if(move_me == 1)
		parv[1]--;

	/* only sends stuff for #channels remotely */

	if(*parv[1] == '!')
	{
		if(!ConfigChannel.use_admin)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support admin prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_ADMIN);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :!%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '@')
	{
		add_user_to_channel(chptr, source_p, CHFL_CHANOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :@%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '%')
	{
		if(!ConfigChannel.use_halfop)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support halfop prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_HALFOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :%s%s",
			      me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '+')
	{
		add_user_to_channel(chptr, source_p, CHFL_VOICE);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :+%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '~')
	{
		if(!ConfigChannel.use_founder)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support founder prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_FOUNDER);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :~%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +u %s",
				     me.name, chptr->chname, source_p->name);
	}
	else
	{
		add_user_to_channel(chptr, source_p, CHFL_PEON);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s JOIN %ld %s +",
			      source_p->id, (long) chptr->channelts, chptr->chname);
		send_channel_join(chptr, source_p);
	}

	/* send the topic... */
	if(chptr->topic != NULL)
	{
		sendto_one(source_p, form_str(RPL_TOPIC), me.name,
			   source_p->name, chptr->chname, chptr->topic);
		sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name,
			   source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time);
	}

	source_p->localClient->last_join_time = rb_current_time();
	channel_member_names(chptr, source_p, 1);

	sendto_realops_snomask(SNO_GENERAL, L_ALL,
			       "OJOIN called for %s by %s!%s@%s",
			       parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p));


	return 0;
}
Esempio n. 30
0
static int
mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;
	struct ConfItem *resv_p;
	struct rb_sockaddr_storage ip;
	char user_trunc[USERLEN + 1], notildeuser_trunc[USERLEN + 1];
	const char *name = NULL;
	const char *username = NULL;
	const char *host = NULL;
	char *mask;
	char *p;
	int host_mask;
	int type;
	int duration;
	char *puser, *phost, *reason, *operreason;
	char reasonbuf[BUFSIZE];

	mask = LOCAL_COPY(parv[1]);

	if (IsChannelName(mask))
	{
		resv_p = hash_find_resv(mask);
		if (resv_p != NULL)
		{
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					resv_p->hold ? 'q' : 'Q',
					resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L,
					resv_p->host, resv_p->passwd);
			/* this is a false positive, so make sure it isn't counted in stats q
			 * --nenolod
			 */
			resv_p->port--;
		}
		else
			sendto_one(source_p, form_str(RPL_NOTESTLINE),
					me.name, source_p->name, parv[1]);
		return 0;
	}

	if((p = strchr(mask, '!')))
	{
		*p++ = '\0';
		name = mask;
		mask = p;

		if(EmptyString(mask))
			return 0;
	}

	if((p = strchr(mask, '@')))
	{
		*p++ = '\0';
		username = mask;
		host = p;

		if(EmptyString(host))
			return 0;
	}
	else
		host = mask;

	/* parses as an IP, check for a dline */
	if((type = parse_netmask(host, &ip, &host_mask)) != HM_HOST)
	{
#ifdef RB_IPV6
		if(type == HM_IPV6)
			aconf = find_dline((struct sockaddr *)&ip, AF_INET6);
		else
#endif
			aconf = find_dline((struct sockaddr *)&ip, AF_INET);

		if(aconf && aconf->status & CONF_DLINE)
		{
			get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason);
			snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason,
				operreason ? "|" : "", operreason ? operreason : "");
			sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				(aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D',
				(aconf->flags & CONF_FLAGS_TEMPORARY) ?
				 (long) ((aconf->hold - rb_current_time()) / 60) : 0L,
				phost, reasonbuf);

			return 0;
		}
		/* Otherwise, aconf is an exempt{} */
		if(aconf == NULL &&
				(duration = is_reject_ip((struct sockaddr *)&ip)))
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					'!',
					duration / 60L,
					host, "Reject cache");
		if(aconf == NULL &&
				(duration = is_throttle_ip((struct sockaddr *)&ip)))
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					'!',
					duration / 60L,
					host, "Throttled");
	}

	if (username != NULL)
	{
		rb_strlcpy(user_trunc, username, sizeof user_trunc);
		rb_strlcpy(notildeuser_trunc, *username == '~' ? username + 1 : username, sizeof notildeuser_trunc);
	}
	else
	{
		rb_strlcpy(user_trunc, "dummy", sizeof user_trunc);
		rb_strlcpy(notildeuser_trunc, "dummy", sizeof notildeuser_trunc);
	}
	/* now look for a matching I/K/G */
	if((aconf = find_address_conf(host, NULL, user_trunc, notildeuser_trunc,
				(type != HM_HOST) ? (struct sockaddr *)&ip : NULL,
				(type != HM_HOST) ? (
#ifdef RB_IPV6
				 (type == HM_IPV6) ? AF_INET6 :
#endif
				  AF_INET) : 0, NULL)))
	{
		static char buf[HOSTLEN+USERLEN+2];

		if(aconf->status & CONF_KILL)
		{
			get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason);
			snprintf(buf, sizeof(buf), "%s@%s",
					puser, phost);
			snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason,
				operreason ? "|" : "", operreason ? operreason : "");
			sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				(aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K',
				(aconf->flags & CONF_FLAGS_TEMPORARY) ?
				 (long) ((aconf->hold - rb_current_time()) / 60) : 0L,
				buf, reasonbuf);
			return 0;
		}
	}

	/* they asked us to check a nick, so hunt for resvs.. */
	if(name && (resv_p = find_nick_resv(name)))
	{
		sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				resv_p->hold ? 'q' : 'Q',
				resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L,
				resv_p->host, resv_p->passwd);

		/* this is a false positive, so make sure it isn't counted in stats q
		 * --nenolod
		 */
		resv_p->port--;
		return 0;
	}

	/* no matching resv, we can print the I: if it exists */
	if(aconf && aconf->status & CONF_CLIENT)
	{
		sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE),
				aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd,
				show_iline_prefix(source_p, aconf, aconf->user),
				aconf->host, aconf->port, aconf->className);
		return 0;
	}

	/* nothing matches.. */
	sendto_one(source_p, form_str(RPL_NOTESTLINE),
			me.name, source_p->name, parv[1]);
	return 0;
}