int is_services_root(User * u)
{
    if ((NSStrictPrivileges && !is_oper(u))
        || (!skeleton && !nick_identified(u)))
        return 0;
    if (skeleton || (u->na->nc->flags & NI_SERVICES_ROOT))
        return 1;
    return 0;
}
/**
 * The suspend command.
 * @param u The user who issued the command
 * @param ci The channel we will be suspending.
 * @param reason The reason given for suspending the channel.
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_suspend(User * u, ChannelInfo *ci, char *reason) {
	Channel *c;

	if (!ci) {
		moduleNoticeLang(ci->bi->nick, u, LANG_SUSPEND_SYNTAX);
		return MOD_CONT;
	}

	if (ForceForbidReason && !reason) {
		moduleNoticeLang(ci->bi->nick, u, LANG_SUSPEND_NO_REASON);
		return MOD_CONT;
	}

	if (readonly) {
		notice_lang(ci->bi->nick, u, READ_ONLY_MODE);
		return MOD_CONT;
	}

	ci->flags |= CI_SUSPENDED;
	ci->forbidby = sstrdup(u->nick);
	if (reason)
		ci->forbidreason = sstrdup(reason);

	if ((c = findchan(ci->name))) {
		struct c_userlist *cu, *next;
		char *av[3];

		for (cu = c->users; cu; cu = next) {
			next = cu->next;

			if (is_oper(cu->user))
				continue;

			av[0] = c->name;
			av[1] = cu->user->nick;
			av[2] = reason ? reason : "CHAN_SUSPEND_REASON";
			xanadu_cmd_kick(ci->bi->nick, av[0], av[1], av[2]);
			do_kick(ci->bi->nick, 3, av);
		}
	}

	if (WallForbid)
		xanadu_cmd_global(ci->bi->nick, "\2%s\2 used SUSPEND on channel \2%s\2",
				u->nick, ci->name);

	alog("%s: %s set SUSPEND for channel %s", ci->bi->nick, u->nick, ci->name);
	notice_lang(ci->bi->nick, u, CHAN_SUSPEND_SUCCEEDED, ci->name);
	send_event(EVENT_CHAN_SUSPENDED, 1, ci->name);

	return MOD_CONT;
}
Exemple #3
0
int list_global_opers(Channel *c, User *u) {
	int j, i , carryon, count = 0;
	User *u2;
	char *access;

	noticeLang(c->ci->bi->nick, u, LANG_GOLIST_HEADER);
	for (j = 0; j < 1024; j++) {
		for (u2 = userlist[j]; u2; u2 = u2->next) {
			carryon = 0;

			/* Prevent listing of users with +H */
			if (finduser((u2->nick)) && !has_umode_H(u2) && !has_umode_B(u2) && !is_ulined(u2->server->name)) {
				i = 0;
				while (i < excempt_nr) {
					if (!ListExempts[i] || !u2->nick)
						break;
					if (my_match_wild_nocase(ListExempts[i], u2->nick)) {
						carryon = 1;
						break;
					}
					i++;
				}

				if (carryon)
					continue;

				if (is_oper(u2)) {
					count++;
					access = getLangString(u->na, LANG_GOLIST_OPER_ONLY);
					if (is_services_oper(u2))
						access = getLangString(u->na, LANG_GOLIST_OPER_AND_SO);
					if (is_services_admin(u2))
						access = getLangString(u->na, LANG_GOLIST_OPER_AND_SA);
					if (is_services_root(u2))
						access = getLangString(u->na, LANG_GOLIST_OPER_AND_SRA);
					notice(c->ci->bi->nick, u->nick, "%-15s  -  %s", u2->nick, access);
				}
			}
		}
	}

	if (count == 0)
		noticeLang(c->ci->bi->nick, u, LANG_GOLIST_NONE);
	noticeLang(c->ci->bi->nick, u, LANG_GOLIST_FOOTER, count);

	return MOD_CONT;
}
Exemple #4
0
int list_admins(Channel *c, User *u) {
	int j, i , carryon, count = 0;
	User *u2;

	noticeLang(c->ci->bi->nick, u, LANG_ADLIST_HEADER);
	for (j = 0; j < 1024; j++) {
		for (u2 = userlist[j]; u2; u2 = u2->next) {
			carryon = 0;

			/* Prevent listing of users with +H */
			if (finduser((u2->nick)) && !has_umode_H(u2) && !has_umode_B(u2) && !is_ulined(u2->server->name)) {
				i = 0;
				while (i < excempt_nr) {
					if (!ListExempts[i] || !u2->nick)
						break;
					if (!stricmp(u2->nick, ListExempts[i]))
						carryon = 1;
					i++;
				}

				if (carryon)
					continue;

				if (is_oper(u2)) {
					if (is_services_root(u2)) {
						count++;
						notice(c->ci->bi->nick, u->nick, "%-15s  -  %s", u2->nick, getLangString(u->na, LANG_ADLIST_SRA));
						continue;
					}
					if (is_services_admin(u2)) {
						count++;
						notice(c->ci->bi->nick, u->nick, "%-15s  -  %s", u2->nick, getLangString(u->na, LANG_ADLIST_SA));
					}
				}
			}
		}
	}

	if (count == 0)
		noticeLang(c->ci->bi->nick, u, LANG_ADLIST_NONE);
	noticeLang(c->ci->bi->nick, u, LANG_ADLIST_FOOTER, count);

	return MOD_CONT;
}
/**
 * The /bs botlist command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_botlist(User * u)
{
    int i, count = 0;
    BotInfo *bi;

    if (!nbots) {
        notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY);
        return MOD_CONT;
    }

    for (i = 0; i < 256; i++) {
        for (bi = botlists[i]; bi; bi = bi->next) {
            if (!(bi->flags & BI_PRIVATE)) {
                if (!count)
                    notice_lang(s_BotServ, u, BOT_BOTLIST_HEADER);
                count++;
                notice_user(s_BotServ, u, "   %-15s  (%s@%s)", bi->nick,
                            bi->user, bi->host);
            }
        }
    }

    if (is_oper(u) && count < nbots) {
        notice_lang(s_BotServ, u, BOT_BOTLIST_PRIVATE_HEADER);

        for (i = 0; i < 256; i++) {
            for (bi = botlists[i]; bi; bi = bi->next) {
                if (bi->flags & BI_PRIVATE) {
                    notice_user(s_BotServ, u, "   %-15s  (%s@%s)",
                                bi->nick, bi->user, bi->host);
                    count++;
                }
            }
        }
    }

    if (!count)
        notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY);
    else
        notice_lang(s_BotServ, u, BOT_BOTLIST_FOOTER, count);
    return MOD_CONT;
}
/**
 * Check and enforce SQlines
 * @param mask of the sqline
 * @param reason for the sqline
 * @return void
 */
void sqline(char *mask, char *reason)
{
    int i;
    Channel *c, *next;
    char *av[3];
    struct c_userlist *cu, *cunext;

    if (ircd->chansqline) {
        if (*mask == '#') {
            xanadu_cmd_sqline(mask, reason);

            for (i = 0; i < 1024; i++) {
                for (c = chanlist[i]; c; c = next) {
                    next = c->next;

                    if (!match_wild_nocase(mask, c->name)) {
                        continue;
                    }
                    for (cu = c->users; cu; cu = cunext) {
                        cunext = cu->next;
                        if (is_oper(cu->user)) {
                            continue;
                        }
                        av[0] = c->name;
                        av[1] = cu->user->nick;
                        av[2] = reason;
                        xanadu_cmd_kick(s_OperServ, av[0], av[1],
                                       "Q-Lined: %s", av[2]);
                        do_kick(s_ChanServ, 3, av);
                    }
                }
            }
        } else {
            xanadu_cmd_sqline(mask, reason);
        }
    } else {
        xanadu_cmd_sqline(mask, reason);
    }
}
/**
 * The /bs assign command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_assign(User * u)
{
    char *chan = strtok(NULL, " ");
    char *nick = strtok(NULL, " ");
    BotInfo *bi;
    ChannelInfo *ci;

    if (readonly)
        notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY);
    else if (!chan || !nick)
        syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX);
    else if (!(bi = findbot(nick)))
        notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick);
    else if (bi->flags & BI_PRIVATE && !is_oper(u))
        notice_lang(s_BotServ, u, PERMISSION_DENIED);
    else if (!(ci = cs_findchan(chan)))
        notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan);
    else if (ci->flags & CI_VERBOTEN)
        notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan);
    else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0))
        notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan);
    else if ((ci->botflags & BS_NOBOT)
             || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u)))
        notice_lang(s_BotServ, u, PERMISSION_DENIED);
    else {
        if (ci->bi)
            unassign(u, ci);
        ci->bi = bi;
        bi->chancount++;
        if (ci->c && ci->c->usercount >= BSMinUsers) {
            bot_join(ci);
        }
        notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name);
        send_event(EVENT_BOT_ASSIGN, 2, ci->name, bi->nick);
    }
    return MOD_CONT;
}
/**
 * ChanKill - Akill an entire channel (got botnet?)
 *
 * /msg OperServ ChanKill +expire #channel reason
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. 
 *
 **/
int do_chankill(User * u)
{
    char *expiry, *channel, *reason;
    time_t expires;
    char breason[BUFSIZE];
    char mask[USERMAX + HOSTMAX + 2];
    struct c_userlist *cu, *next;
    Channel *c;

    channel = strtok(NULL, " ");
    if (channel && *channel == '+') {
        expiry = channel;
        channel = strtok(NULL, " ");
    } else {
        expiry = NULL;
    }

    expires = expiry ? dotime(expiry) : ChankillExpiry;
    if (expiry && isdigit(expiry[strlen(expiry) - 1]))
        expires *= 86400;
    if (expires != 0 && expires < 60) {
        notice_lang(s_OperServ, u, BAD_EXPIRY_TIME);
        return MOD_CONT;
    } else if (expires > 0) {
        expires += time(NULL);
    }

    if (channel && (reason = strtok(NULL, ""))) {

        if (AddAkiller) {
            snprintf(breason, sizeof(breason), "[%s] %s", u->nick, reason);
            reason = sstrdup(breason);
        }

        if ((c = findchan(channel))) {
            for (cu = c->users; cu; cu = next) {
                next = cu->next;
                if (is_oper(cu->user)) {
                    continue;
                }
                (void) strncpy(mask, "*@", 3); /* Use *@" for the akill's, */
                strncat(mask, cu->user->host, HOSTMAX);
                add_akill(NULL, mask, s_OperServ, expires, reason);
                check_akill(cu->user->nick, cu->user->username,
                            cu->user->host, NULL, NULL);
            }
            if (WallOSAkill) {
                xanadu_cmd_global(s_OperServ, "%s used CHANKILL on %s (%s)",
                                 u->nick, channel, reason);
            }
        } else {
            notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, channel);
        }
        if (AddAkiller) {
            free(reason);
        }
    } else {
        syntax_error(s_OperServ, u, "CHANKILL", OPER_CHANKILL_SYNTAX);
    }
    return MOD_CONT;
}
int add_sgline(User * u, char *mask, const char *by, const time_t expires,
               const char *reason)
{
    int deleted = 0, i;
    SXLine *entry;
    User *u2, *next;
    char buf[BUFSIZE];
    *buf = '\0';

    /* Checks whether there is an SGLINE that already covers
     * the one we want to add, and whether there are SGLINEs
     * that would be covered by this one.
     * If so, warn the user in the first case and cleanup
     * the useless SGLINEs in the second.
     */

    if (!mask) {
        return -1;
    }

    if (sglines.count > 0) {

        for (i = sglines.count - 1; i >= 0; i--) {
            entry = sglines.list[i];

            if (!entry)
                continue;

            if (!stricmp(entry->mask, mask)) {
                if (entry->expires >= expires || entry->expires == 0) {
                    if (u)
                        notice_lang(s_OperServ, u, OPER_SGLINE_EXISTS,
                                    mask);
                    return -1;
                } else {
                    entry->expires = expires;
                    if (u)
                        notice_lang(s_OperServ, u, OPER_SGLINE_CHANGED,
                                    entry->mask);
                    return -2;
                }
            }

            if (match_wild_nocase(entry->mask, mask)
                && (entry->expires >= expires || entry->expires == 0)) {
                if (u)
                    notice_lang(s_OperServ, u, OPER_SGLINE_ALREADY_COVERED,
                                mask, entry->mask);
                return -1;
            }

            if (match_wild_nocase(mask, entry->mask)
                && (entry->expires <= expires || expires == 0)) {
                slist_delete(&sglines, i);
                deleted++;
            }
        }

    }

    /* We can now check whether the list is full or not. */
    if (slist_full(&sglines)) {
        if (u)
            notice_lang(s_OperServ, u, OPER_SGLINE_REACHED_LIMIT,
                        sglines.limit);
        return -1;
    }

    /* We can now (really) add the SGLINE. */
    entry = scalloc(sizeof(SXLine), 1);
    if (!entry)
        return -1;

    entry->mask = sstrdup(mask);
    entry->by = sstrdup(by);
    entry->reason = sstrdup(reason);
    entry->seton = time(NULL);
    entry->expires = expires;

    slist_add(&sglines, entry);

    xanadu_cmd_sgline(entry->mask, entry->reason);

    if (KillonSGline && !ircd->sglineenforce) {
        snprintf(buf, (BUFSIZE - 1), "G-Lined: %s", entry->reason);
        u2 = firstuser();
        while (u2) {
            next = nextuser();
            if (!is_oper(u2)) {
                if (match_wild_nocase(entry->mask, u2->realname)) {
                    kill_user(ServerName, u2->nick, buf);
                }
            }
            u2 = next;
        }
    }
    return deleted;
}
Exemple #10
0
int do_core_kickban(User * u, Channel *c, char *target, char *reason) {
	ChannelInfo *ci = c->ci;
	User *u2;
	int is_same, exists;
	char *av[2];

	if (!target)
		target = u->nick;

	is_same = (target == u->nick) ? 1 : (stricmp(target, u->nick) == 0);

	if (is_same) {
		u2 = u;
		exists = 1;
	} else
		exists = ((u2 = finduser(target)) ? 1 : 0);

	if (!is_same ? !check_access(u, ci, CA_BAN) : !check_access(u, ci, CA_BANME)) {
		notice_lang(ci->bi->nick, u, ACCESS_DENIED);
	} else if (!is_same && exists && (ci->flags & CI_PEACE) && (get_access(u2, ci) >= get_access(u, ci))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	} else if (exists && ((ircd->protectedumode && is_protected(u2)) && !is_founder(u, ci))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	/**
	 * Dont ban the user on channels where he is excepted
	 * to prevent services <-> server wars.
	 **/
	} else if (exists && (ircd->except && is_excepted(ci, u2))) {
		notice_lang(ci->bi->nick, u, CHAN_EXCEPTED, u2->nick, ci->name);
	} else if (!exists && (ircd->except && is_excepted_mask(ci, target))) {
		notice_lang(ci->bi->nick, u, CHAN_EXCEPTED, target, ci->name);
	} else if (exists && RestrictKB && ((!is_founder(u, ci) && is_services_oper(u2)) ||
			(is_founder(u, ci) && is_services_admin(u2)))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	} else if (stricmp(target, ci->bi->nick) == 0) {
		bot_raw_ban(u, ci, u->nick, "Oops!");
	} else {
		if (exists) {
			if (is_on_chan(ci->c, u2)) {
				if (!reason)
					bot_raw_ban(u, ci, target, "Requested");
				else
					bot_raw_ban(u, ci, target, reason);
			}

		} else if (my_match_wild_nocase("*@*", target)) {
			char mask[BUFSIZE];

			/* If we get a *@* target we need to add the *!... */
			if (!my_match_wild_nocase("*!*@*", target))
				snprintf(mask, BUFSIZE, "*!%s", target);
			else
				snprintf(mask, BUFSIZE, "%s", target);

			/* Only continue if the mask doesn't match an exception or is otherwise prohibited.. */
			if (check_banmask(u, c, mask)) {
				struct c_userlist *cu = NULL, *next = NULL;

				av[0] = "+b";
				av[1] = mask;

				anope_cmd_mode(ci->bi->nick, c->name, "+b %s", av[1]);
				chan_set_modes(ci->bi->nick, c, 2, av, 1);

				cu = c->users;
				while (cu) {
					next = cu->next;
					/* This only checks against the cloacked host & vhost for normal users.
					 * IPs are only checked when triggered by an oper.. */
					if (is_oper(u) ? match_usermask_full(mask, cu->user, true) : match_usermask(mask, cu->user)) {
						if (!reason)
							bot_raw_kick(u, ci, cu->user->nick, "Requested");
						else
							bot_raw_kick(u, ci, cu->user->nick, reason);
					}
					cu = next;
				}
			}
		} else
			noticeLang(ci->bi->nick, u, LANG_REQ_NICK_OR_MASK);
	}
	return MOD_CONT;
}
Exemple #11
0
int do_core_kick(User * u, Channel *c, char *target, char *reason) {
	ChannelInfo *ci = c->ci;
	User *u2;
	int is_same, exists;

	if (!target)
		target = u->nick;

	is_same = (target == u->nick) ? 1 : (stricmp(target, u->nick) == 0);

	if (is_same) {
		u2 = u;
		exists = 1;
	} else
		exists = ((u2 = finduser(target)) ? 1 : 0);

	if (!is_same ? !check_access(u, ci, CA_KICK) : !check_access(u, ci, CA_KICKME)) {
		notice_lang(ci->bi->nick, u, ACCESS_DENIED);
	} else if (!is_same && exists && (ci->flags & CI_PEACE) && (get_access(u2, ci) >= get_access(u, ci))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	} else if (exists && ((ircd->protectedumode && is_protected(u2)) && !is_founder(u, ci))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	} else if (exists && RestrictKB && ((!is_founder(u, ci) && is_services_oper(u2)) ||
			(is_founder(u, ci) && is_services_admin(u2)))) {
		notice_lang(ci->bi->nick, u, PERMISSION_DENIED);
	} else if (stricmp(target, ci->bi->nick) == 0) {
		bot_raw_kick(u, ci, u->nick, "Oops!");
	} else {
		if (exists) {
			if (is_on_chan(ci->c, u2)) {
				if (!reason)
					bot_raw_kick(u, ci, target, "Requested");
				else
					bot_raw_kick(u, ci, target, reason);
			}

		} else {
			char mask[BUFSIZE];
			struct c_userlist *cu = NULL, *next = NULL;

			if (my_match_wild_nocase("*!*@*", target))
				snprintf(mask, BUFSIZE, "%s", target);
			/* If we get a *@* target we need to add the *!... */
			else if (my_match_wild_nocase("*@*", target))
				snprintf(mask, BUFSIZE, "*!%s", target);
			else if (my_match_wild_nocase("*!*", target))
				snprintf(mask, BUFSIZE, "%s@*", target);
			/* If we get a * target we need to add the !*@* (assume nick)... */
			else
				snprintf(mask, BUFSIZE, "%s!*@*", target);

			cu = c->users;
			while (cu) {
				next = cu->next;
				/* This only checks against the cloacked host & vhost for normal users.
				 * IPs are only checked when triggered by an oper.. */
				if (is_oper(u) ? match_usermask_full(mask, cu->user, true) : match_usermask(mask, cu->user)) {
					/* Check whether we are allowed to kick this matching user.. */
					if (!((ircd->protectedumode && is_protected(cu->user) && !is_founder(u, ci))
							|| ((ci->flags & CI_PEACE) && (get_access(cu->user, ci) >= get_access(u, ci)))
							|| (RestrictKB && ((!is_founder(u, ci) && is_services_oper(cu->user)) ||
							(is_founder(u, ci) && is_services_admin(cu->user)))))) {
						if (!reason)
							bot_raw_kick(u, ci, cu->user->nick, "Requested");
						else
							bot_raw_kick(u, ci, cu->user->nick, reason);
					}
				}
				cu = next;
			}
		}
	}
	return MOD_CONT;
}
Exemple #12
0
IgnoreData *get_ignore(const char *nick)
{
    IgnoreData *ign, *prev;
    time_t now = time(NULL);
    IgnoreData **whichlist = &ignore[tolower(nick[0])];
    User *u = finduser(nick);
    IgnoreData **whichlist2 = NULL;
    /* Bleah, this doesn't work. I need a way to get the first char of u->username.
       /if (u) whichlist2 = &ignore[tolower(u->username[0])]; */
    IgnoreData **whichlistast = &ignore[42];    /* * */
    IgnoreData **whichlistqst = &ignore[63];    /* ? */
    int finished = 0;


    /* User has disabled the IGNORE system */
    if (!allow_ignore) {
        return NULL;
    }

    /* if an oper gets on the ignore list we let them privmsg, this will allow
       them in places we call get_ignore to get by */
    if (u && is_oper(u)) {
        return NULL;
    }

    for (ign = *whichlist, prev = NULL; ign; prev = ign, ign = ign->next) {
        if (stricmp(ign->who, nick) == 0) {
            finished = 1;
            break;
        }
    }
    /* We can only do the next checks if we have an actual user -GD */
    if (u) {
        if (!finished && whichlist2) {
            for (ign = *whichlist2, prev = NULL; ign;
                 prev = ign, ign = ign->next) {
                if (match_usermask(ign->who, u)) {
                    finished = 1;
                    break;
                }
            }
        }
        if (!finished) {
            for (ign = *whichlistast, prev = NULL; ign;
                 prev = ign, ign = ign->next) {
                if (match_usermask(ign->who, u)) {
                    finished = 1;
                    break;
                }
            }
        }
        if (!finished) {
            for (ign = *whichlistqst, prev = NULL; ign;
                 prev = ign, ign = ign->next) {
                if (match_usermask(ign->who, u)) {
                    finished = 1;
                    break;
                }
            }
        }
    }
    if (ign && ign->time <= now) {
        if (prev)
            prev->next = ign->next;
        else
            *whichlist = ign->next;
        free(ign);
        ign = NULL;
    }
    return ign;
}
Exemple #13
0
void delete_user(User * user)
{
    struct u_chanlist *c, *c2;
    struct u_chaninfolist *ci, *ci2;
    char *realname;

    if (LogUsers) {
        realname = normalizeBuffer(user->realname);
        if (ircd->vhost) {
            alog("LOGUSERS: %s (%s@%s => %s) (%s) left the network (%s).",
                 user->nick, user->username, user->host,
                 (user->vhost ? user->vhost : "(none)"),
                 realname, user->server->name);
        } else {
            alog("LOGUSERS: %s (%s@%s) (%s) left the network (%s).",
                 user->nick, user->username, user->host,
                 realname, user->server->name);
        }
        free(realname);
    }
    send_event(EVENT_USER_LOGOFF, 1, user->nick);

    if (debug >= 2)
        alog("debug: delete_user() called");
    usercnt--;
    if (is_oper(user))
        opcnt--;
    if (debug >= 2)
        alog("debug: delete_user(): free user data");
    free(user->username);
    free(user->host);
    if (user->chost)
        free(user->chost);
    if (user->vhost)
        free(user->vhost);
    if (user->vident)
        free(user->vident);
    if (user->uid) {
        free(user->uid);
    }
    Anope_Free(user->realname);
    Anope_Free(user->hostip);
    if (debug >= 2) {
        alog("debug: delete_user(): remove from channels");
    }
    c = user->chans;
    while (c) {
        c2 = c->next;
        chan_deluser(user, c->chan);
        free(c);
        c = c2;
    }
    /* This called only here now */
    cancel_user(user);
    if (user->na)
        user->na->u = NULL;
    if (debug >= 2)
        alog("debug: delete_user(): free founder data");
    ci = user->founder_chans;
    while (ci) {
        ci2 = ci->next;
        free(ci);
        ci = ci2;
    }

    if (user->nickTrack)
        free(user->nickTrack);

    moduleCleanStruct(&user->moduleData);

    if (debug >= 2)
        alog("debug: delete_user(): delete from list");
    if (user->prev)
        user->prev->next = user->next;
    else
        userlist[HASH(user->nick)] = user->next;
    if (user->next)
        user->next->prev = user->prev;
    if (debug >= 2)
        alog("debug: delete_user(): free user structure");
    free(user);
    if (debug >= 2)
        alog("debug: delete_user() done");
}
Exemple #14
0
int do_resetpass(User * u)
{
    char *buffer = NULL;
    char *nick = NULL;
    char *email = NULL;

    char passcode[PASSCODELEN];
    char *callBackinfo[1];
    NickAlias *na = NULL;

    if ((RestrictReset == 1) && !(is_oper(u))) {
        notice_lang(s_NickServ, u, ACCESS_DENIED);
        return MOD_CONT;
    }

    buffer = moduleGetLastBuffer();
    nick = myStrGetToken(buffer, ' ', 0);
    email = myStrGetToken(buffer, ' ', 1);

    if (!nick) {
        moduleNoticeLang(s_NickServ, u, RESETPASS_SYNTAX);
    } else if (!anope_valid_nick(nick)) {
        notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
    } else if (!(na = findnick(nick))) {
        notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
    } else if (na->status & NS_VERBOTEN) {
         notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick);
    } else if (na->nc->flags & NI_SUSPENDED) {
        notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick);
    } else if (!na->nc->email) {
         notice_user(s_NickServ, u, "%s has no email associated with their account.", na->nick);
    } else if (moduleGetData(&na->nc->moduleData, MODULEDATAKEY)) {
        moduleNoticeLang(s_NickServ, u, RESETPASS_ALREADY_REQUESTED1,
                         na->nick);
        moduleNoticeLang(s_NickServ, u, RESETPASS_ALREADY_REQUESTED2); 
    } else if (!email && !is_oper(u) && !is_helpop(u)) {
	notice(s_NickServ, u->nick, "You need to provide the e-mail address associated with the account you are trying to reset the password on.");
	notice(s_NickServ, u->nick, "Syntax: /ns resetpass <nickname> <e-mail>");
    } else if (!is_oper(u) && !is_helpop(u) && strcasecmp(email, na->nc->email)) {
	notice(s_NickServ, u->nick, "The e-mail address %s does not match the one associated with account %s.", email, na->nc->display);
    } else {
        generatePassCode(passcode);
        moduleAddData(&na->nc->moduleData, MODULEDATAKEY, passcode);
        if (do_sendmail(u, na) != 0) {
            alog(LOG_COULDNT_SENDMAIL, MYNAME, na->nick);
            moduleDelData(&na->nc->moduleData, MODULEDATAKEY);
        } else {
            callBackinfo[0] = na->nick;
            moduleAddCallback(MYNAME, time(NULL) + ExpirePassCode, expirePassCode, 1, callBackinfo);
            alog(LOG_RESETPASS_REQUESTED, MYNAME, u->nick, na->nick);
            moduleNoticeLang(s_NickServ, u, RESETPASS_SUCCESS, na->nick);
            moduleNoticeLang(s_NickServ, u, RESETPASS_INSTRUC);
        }
    }

    if (nick)
    	free(nick);
    if (email)
	free(email);

    return MOD_CONT;
}
Exemple #15
0
/**
 * The /ns list command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
static int do_list(User * u)
{

/* SADMINS can search for nicks based on their NS_VERBOTEN and NS_NO_EXPIRE
 * status. The keywords FORBIDDEN and NOEXPIRE represent these two states
 * respectively. These keywords should be included after the search pattern.
 * Multiple keywords are accepted and should be separated by spaces. Only one
 * of the keywords needs to match a nick's state for the nick to be displayed.
 * Forbidden nicks can be identified by "[Forbidden]" appearing in the last
 * seen address field. Nicks with NOEXPIRE set are preceeded by a "!". Only
 * SADMINS will be shown forbidden nicks and the "!" indicator.
 * Syntax for sadmins: LIST pattern [FORBIDDEN] [NOEXPIRE]
 * -TheShadow
 *
 * UPDATE: SUSPENDED keyword is now accepted as well.
 */


    char *pattern = strtok(NULL, " ");
    char *keyword;
    NickAlias *na;
    NickCore *mync;
    int nnicks, i;
    char buf[BUFSIZE];
    int is_servadmin = is_services_admin(u);
    int16 matchflags = 0;
    NickRequest *nr = NULL;
    int nronly = 0;
    int susp_keyword = 0;
    char noexpire_char = ' ';
    int count = 0, from = 0, to = 0, tofree = 0;
    char *tmp = NULL;
    char *s = NULL;

    if (!(!NSListOpersOnly || (is_oper(u)))) {  /* reverse the help logic */
        notice_lang(s_NickServ, u, ACCESS_DENIED);
        return MOD_STOP;
    }

    if (!pattern) {
        syntax_error(s_NickServ, u, "LIST",
                     is_servadmin ? NICK_LIST_SERVADMIN_SYNTAX :
                     NICK_LIST_SYNTAX);
    } else {

        if (pattern) {
            if (pattern[0] == '#') {
                tmp = myStrGetOnlyToken((pattern + 1), '-', 0); /* Read FROM out */
                if (!tmp) {
                	notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE);
                    return MOD_CONT;
                }
                for (s = tmp; *s; s++) {
                    if (!isdigit(*s)) {
                        free(tmp);
	                	notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE);
                        return MOD_CONT;
                    }
                }
                from = atoi(tmp);
                free(tmp);
                tmp = myStrGetTokenRemainder(pattern, '-', 1);  /* Read TO out */
                if (!tmp) {
                	notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE);
                    return MOD_CONT;
                }
                for (s = tmp; *s; s++) {
                    if (!isdigit(*s)) {
                        free(tmp);
	                	notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE);
                        return MOD_CONT;
                    }
                }
                to = atoi(tmp);
                free(tmp);
                pattern = sstrdup("*");
                tofree = 1;
            }
        }

        nnicks = 0;

        while (is_servadmin && (keyword = strtok(NULL, " "))) {
            if (stricmp(keyword, "FORBIDDEN") == 0)
                matchflags |= NS_VERBOTEN;
            if (stricmp(keyword, "NOEXPIRE") == 0)
                matchflags |= NS_NO_EXPIRE;
            if (stricmp(keyword, "SUSPENDED") == 0)
                susp_keyword = 1;
            if (stricmp(keyword, "UNCONFIRMED") == 0)
                nronly = 1;
        }

        mync = (nick_identified(u) ? u->na->nc : NULL);

        notice_lang(s_NickServ, u, NICK_LIST_HEADER, pattern);
        if (nronly != 1) {
            for (i = 0; i < 1024; i++) {
                for (na = nalists[i]; na; na = na->next) {
                    /* Don't show private and forbidden nicks to non-services admins. */
                    if ((na->status & NS_VERBOTEN) && !is_servadmin)
                        continue;
                    if ((na->nc->flags & NI_PRIVATE) && !is_servadmin
                        && na->nc != mync)
                        continue;
                    if ((matchflags != 0) && !(na->status & matchflags) && (susp_keyword == 0))
                        continue;
		    else if ((susp_keyword == 1) && !(na->nc->flags & NI_SUSPENDED))
                        continue;

                    /* We no longer compare the pattern against the output buffer.
                     * Instead we build a nice nick!user@host buffer to compare.
                     * The output is then generated separately. -TheShadow */
                    snprintf(buf, sizeof(buf), "%s!%s", na->nick,
                             (na->last_usermask
                              && !(na->status & NS_VERBOTEN)) ? na->
                             last_usermask : "*@*");
                    if (stricmp(pattern, na->nick) == 0
                        || match_wild_nocase(pattern, buf)) {

                        if ((((count + 1 >= from) && (count + 1 <= to))
                             || ((from == 0) && (to == 0)))
                            && (++nnicks <= NSListMax)) {
                            if (is_servadmin
                                && (na->status & NS_NO_EXPIRE))
                                noexpire_char = '!';
                            else {
                                noexpire_char = ' ';
                            }
                            if ((na->nc->flags & NI_HIDE_MASK)
                                && !is_servadmin && na->nc != mync) {
                                snprintf(buf, sizeof(buf),
                                         "%-20s  [Hostname Hidden]",
                                         na->nick);
                            } else if (na->status & NS_VERBOTEN) {
                                snprintf(buf, sizeof(buf),
                                         "%-20s  [Forbidden]", na->nick);
                            } else if (na->nc->flags & NI_SUSPENDED) {
                                snprintf(buf, sizeof(buf),
                                         "%-20s  [Suspended]", na->nick);
                            } else {
                                snprintf(buf, sizeof(buf), "%-20s  %s",
                                         na->nick, na->last_usermask);
                            }
                            notice_user(s_NickServ, u, "   %c%s",
                                        noexpire_char, buf);
                        }
                        count++;
                    }
                }
            }
        }

        if (nronly == 1 || (is_servadmin && matchflags == 0 && susp_keyword == 0)) {
            noexpire_char = ' ';
            for (i = 0; i < 1024; i++) {
                for (nr = nrlists[i]; nr; nr = nr->next) {
                    snprintf(buf, sizeof(buf), "%s!*@*", nr->nick);
                    if (stricmp(pattern, nr->nick) == 0
                        || match_wild_nocase(pattern, buf)) {
                        if (++nnicks <= NSListMax) {
                            snprintf(buf, sizeof(buf),
                                     "%-20s  [UNCONFIRMED]", nr->nick);
                            notice_user(s_NickServ, u, "   %c%s",
                                        noexpire_char, buf);
                        }
                    }
                }
            }
        }
        notice_lang(s_NickServ, u, NICK_LIST_RESULTS,
                    nnicks > NSListMax ? NSListMax : nnicks, nnicks);
    }
    if (tofree)
        free(pattern);
    return MOD_CONT;
}
Exemple #16
0
/**
 * Add the help response to anopes /ns help output.
 * @param u The user who is requesting help
 **/
static void myNickServHelp(User * u)
{
    if (!NSListOpersOnly || (is_oper(u))) {
        notice_lang(s_NickServ, u, NICK_HELP_CMD_LIST);
    }
}
Exemple #17
0
/**
 * Add the help response to anopes /os help output.
 * @param u The user who is requesting help
 **/
void myOperServHelp(User * u)
{
    if (is_oper(u)) {
        notice_lang(s_OperServ, u, OPER_HELP_CMD_ADMIN);
    }
}
Exemple #18
0
/**
 * The /cs forbid command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
static int do_forbid(User * u)
{
    Channel *c;
    ChannelInfo *ci;
    char *chan = strtok(NULL, " ");
    char *reason = strtok(NULL, "");
    Entry *cur, *enext;

    /* Assumes that permission checking has already been done. */
    if (!chan || (ForceForbidReason && !reason)) {
        syntax_error(s_ChanServ, u, "FORBID",
                     (ForceForbidReason ? CHAN_FORBID_SYNTAX_REASON :
                      CHAN_FORBID_SYNTAX));
        return MOD_CONT;
    }
    if (*chan != '#') {
        notice_lang(s_ChanServ, u, CHAN_SYMBOL_REQUIRED);
        return MOD_CONT;
    } else if (!anope_valid_chan(chan)) {
        notice_lang(s_ChanServ, u, CHAN_X_INVALID, chan);
        return MOD_CONT;
    }
    if (readonly)
        notice_lang(s_ChanServ, u, READ_ONLY_MODE);
    if ((ci = cs_findchan(chan)) != NULL) {
        delchan(ci);
        send_event(EVENT_CHAN_DROP, 1, chan);
    }
    ci = makechan(chan);
    if (ci) {
        ci->flags |= CI_VERBOTEN;
        ci->forbidby = sstrdup(u->nick);
        if (reason)
            ci->forbidreason = sstrdup(reason);

        if ((c = findchan(ci->name))) {
            struct c_userlist *cu, *next;
            char *av[3];

            /* Before banning everyone, it might be prudent to clear +e and +I lists.. 
             * to prevent ppl from rejoining.. ~ Viper */
            if (ircd->except && c->excepts && c->excepts->count) {
                av[0] = sstrdup("-e");
                for (cur = c->excepts->entries; cur; cur = enext) {
                    enext = cur->next;
                    av[1] = sstrdup(cur->mask);
                    anope_cmd_mode(whosends(ci), chan, "-e %s", cur->mask);
                    chan_set_modes(whosends(ci), c, 2, av, 0);
                    free(av[1]);
                }
                free(av[0]);
            }
            if (ircd->invitemode && c->invites && c->invites->count) {
                av[0] = sstrdup("-I");
                for (cur = c->invites->entries; cur; cur = enext) {
                    enext = cur->next;
                    av[1] = sstrdup(cur->mask);
                    anope_cmd_mode(whosends(ci), chan, "-I %s", cur->mask);
                    chan_set_modes(whosends(ci), c, 2, av, 0);
                    free(av[1]);
                }
                free(av[0]);
            }

            for (cu = c->users; cu; cu = next) {
                next = cu->next;

                if (is_oper(cu->user))
                    continue;

                av[0] = c->name;
                av[1] = cu->user->nick;
                av[2] = reason ? reason : "CHAN_FORBID_REASON";
                anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]);
                do_kick(s_ChanServ, 3, av);
            }
        }

        if (WallForbid)
            anope_cmd_global(s_ChanServ,
                             "\2%s\2 used FORBID on channel \2%s\2",
                             u->nick, ci->name);

        if (ircd->chansqline) {
            anope_cmd_sqline(ci->name, ((reason) ? reason : "Forbidden"));
        }

        alog("%s: %s set FORBID for channel %s", s_ChanServ, u->nick,
             ci->name);
        notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan);
        send_event(EVENT_CHAN_FORBIDDEN, 1, chan);
    } else {
        alog("%s: Valid FORBID for %s by %s failed", s_ChanServ, ci->name,
             u->nick);
        notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan);
    }
    return MOD_CONT;
}
int do_addnick(User * u)
{
    NickAlias *na, *target;
    NickCore *nc;
    char *nick = strtok(NULL, " ");
    char *pass = strtok(NULL, " ");
    int i;
    char tsbuf[16];
    char modes[512];
    int len;

    if (NSEmailReg && (findrequestnick(u->nick))) {
        notice_lang(s_NickServ, u, NS_REQUESTED);
        return MOD_CONT;
    }

    if (readonly) {
        notice_lang(s_NickServ, u, NS_ADDNICK_DISABLED);
        return MOD_CONT;
    }
    if (checkDefCon(DEFCON_NO_NEW_NICKS)) {
        notice_lang(s_NickServ, u, OPER_DEFCON_DENIED);
        return MOD_CONT;
    }

    if (RestrictOperNicks) {
        for (i = 0; i < RootNumber; i++) {
            if (stristr(u->nick, ServicesRoots[i]) && !is_oper(u)) {
                notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED,
                            u->nick);
                return MOD_CONT;
            }
        }
        for (i = 0; i < servadmins.count && (nc = servadmins.list[i]); i++) {
            if (stristr(u->nick, nc->display) && !is_oper(u)) {
                notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED,
                            u->nick);
                return MOD_CONT;
            }
        }
        for (i = 0; i < servopers.count && (nc = servopers.list[i]); i++) {
            if (stristr(u->nick, nc->display) && !is_oper(u)) {
                notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED,
                            u->nick);
                return MOD_CONT;
            }
        }
    }

    if (!nick || !pass) {
        syntax_error(s_NickServ, u, "ADDNICK", NS_ADDNICK_SYNTAX);
    } else if (!(target = findnick(nick))) {
        notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
    } else if (time(NULL) < u->lastnickreg + NSRegDelay) {
        notice_lang(s_NickServ, u, NS_ADDNICK_PLEASE_WAIT, NSRegDelay);
    } else if (u->na && (u->na->status & NS_VERBOTEN)) {
        alog("%s: %s@%s tried to use ADDNICK from forbidden nick %s.",
             s_NickServ, u->username, u->host, u->nick);
        notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u->nick);
    } else if (u->na && (u->na->nc->flags & NI_SUSPENDED)) {
        alog("%s: %s!%s@%s tried to use ADDNICK from suspended nick %s.",
             s_NickServ, u->nick, u->username, u->host, target->nick);
        notice_lang(s_NickServ, u, NICK_X_SUSPENDED, u->nick);
    } else if (u->na && NSNoGroupChange) {
        notice_lang(s_NickServ, u, NS_ADDNICK_CHANGE_DISABLED, s_NickServ);
    } else if (u->na && !nick_identified(u)) {
        notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
    } else if (target && (target->nc->flags & NI_SUSPENDED)) {
        alog("%s: %s!%s@%s tried to use GROUP from SUSPENDED nick %s",
             s_NickServ, u->nick, u->username, u->host, target->nick);
        notice_lang(s_NickServ, u, NICK_X_SUSPENDED, target->nick);
    } else if (target->status & NS_VERBOTEN) {
        notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
    } else if (u->na && target->nc == u->na->nc) {
        notice_lang(s_NickServ, u, NS_ADDNICK_SAME, target->nick);
    } else if (NSMaxAliases && (target->nc->aliases.count >= NSMaxAliases)
               && !nick_is_services_admin(target->nc)) {
        notice_lang(s_NickServ, u, NS_ADDNICK_TOO_MANY, target->nick,
                    s_NickServ, s_NickServ);
    } else if (enc_check_password(pass, target->nc->pass) != 1) {
        alog("%s: Failed ADDNICK for %s!%s@%s (invalid password).",
             s_NickServ, u->nick, u->username, u->host);
        notice_lang(s_NickServ, u, PASSWORD_INCORRECT);
        bad_password(u);
    } else {
        /* If the nick is already registered, drop it.
         * If not, check that it is valid.
         */
        if (u->na) {
            delnick(u->na);
        } else {
            int prefixlen = strlen(NSGuestNickPrefix);
            int nicklen = strlen(u->nick);

            if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1
                && stristr(u->nick, NSGuestNickPrefix) == u->nick
                && strspn(u->nick + prefixlen,
                          "1234567890") == nicklen - prefixlen) {
                notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED,
                            u->nick);
                return MOD_CONT;
            }
        }
        na = makealias(u->nick, target->nc);

        if (na) {
            na->last_usermask =
                scalloc(strlen(common_get_vident(u)) +
                        strlen(common_get_vhost(u)) + 2, 1);
            sprintf(na->last_usermask, "%s@%s", common_get_vident(u),
                    common_get_vhost(u));
            na->last_realname = sstrdup(u->realname);
            na->time_registered = na->last_seen = time(NULL);
            na->status = (int16) (NS_IDENTIFIED | NS_RECOGNIZED);

            if (!(na->nc->flags & NI_SERVICES_ROOT)) {
                for (i = 0; i < RootNumber; i++) {
                    if (!stricmp(ServicesRoots[i], u->nick)) {
                        na->nc->flags |= NI_SERVICES_ROOT;
                        break;
                    }
                }
            }

            u->na = na;
            na->u = u;

#ifdef USE_RDB
            /* Is this really needed? Since this is a new alias it will get
             * its unique id on the next update, since it was previously
             * deleted by delnick. Must observe...
             */
            if (rdb_open()) {
                rdb_save_ns_alias(na);
                rdb_close();
            }
#endif
            send_event(EVENT_GROUP, 1, u->nick);
            alog("%s: %s!%s@%s makes %s join group of %s (%s) (e-mail: %s)", s_NickServ, u->nick, u->username, u->host, u->nick, target->nick, target->nc->display, (target->nc->email ? target->nc->email : "none"));
            notice_lang(s_NickServ, u, NS_ADDNICK_SUCCESS, target->nick);

            u->lastnickreg = time(NULL);
            snprintf(tsbuf, sizeof(tsbuf), "%lu",
                     (unsigned long int) u->timestamp);
            if (ircd->modeonreg) {
                len = strlen(ircd->modeonreg);
                strncpy(modes,ircd->modeonreg,512);
	       if(ircd->rootmodeonid && is_services_root(u)) { 
                    strncat(modes,ircd->rootmodeonid,512-len);
	        } else if(ircd->adminmodeonid && is_services_admin(u)) {
                    strncat(modes,ircd->adminmodeonid,512-len);
	        } else if(ircd->opermodeonid && is_services_oper(u)) {
                    strncat(modes,ircd->opermodeonid,512-len);
                }
                if (ircd->tsonmode) {
                    common_svsmode(u, modes, tsbuf);
                } else {
                    common_svsmode(u, modes, NULL);
                }
            }

            check_memos(u);
        } else {
            alog("%s: makealias(%s) failed", s_NickServ, u->nick);
            notice_lang(s_NickServ, u, NS_ADDNICK_FAILED);
        }
    }
    return MOD_CONT;
}
Exemple #20
0
/**
 * Handle STATS commands
 *
 * @param source is the nick of the person whom sent the stats command
 * @param ac is the parameter count
 * @param av is the parameter array
 *
 * @return always returns MOD_CONT
 */
int m_stats(char *source, int ac, char **av)
{
    User *u;
    Dadmin *a;
    int i;

    if (ac < 1)
        return MOD_CONT;

    switch (*av[0]) {
    case 'l':
        u = user_find(source);

        if (u && is_oper(u)) {

            denora_cmd_numeric
                (source, 211,
                 "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime");
            denora_cmd_numeric(source, 211, "%s %d %d %d %d %d %d %ld",
                               RemoteServer, write_buffer_len(),
                               total_written, total_recmsg,
                               read_buffer_len(), total_read,
                               total_sendmsg,
                               time(NULL) - denora->start_time);
        }

        denora_cmd_219(source, NULL);
        break;
    case 'o':
    case 'O':
/* Check whether the user is an operator */
        u = user_find(source);
        if (u && !is_oper(u) && HideStatsO) {
            denora_cmd_219(source, av[0]);
        } else {
            for (i = 0; i < 1024; i++) {
                for (a = adminlists[i]; a; a = a->next) {
                    denora_cmd_numeric(source, 243, "O * * %s Admin 0",
                                       a->name);
                }
            }
            denora_cmd_219(source, av[0]);
        }

        break;

    case 'u':{
            int uptime = time(NULL) - denora->start_time;
            denora_cmd_numeric(source, 242,
                               ":Stats up %d day%s, %02d:%02d:%02d",
                               uptime / 86400,
                               (uptime / 86400 == 1) ? "" : "s",
                               (uptime / 3600) % 24, (uptime / 60) % 60,
                               uptime % 60);
            denora_cmd_numeric(source, 250,
                               ":Current users: %d (%d ops); maximum %d",
                               stats->users, stats->opers,
                               stats->users_max);
            denora_cmd_219(source, av[0]);
            break;
        }                       /* case 'u' */

    default:
        denora_cmd_219(source, av[0]);
        break;
    }
    return MOD_CONT;
}
Exemple #21
0
/**
 * Adds a new user to anopes internal userlist.
 *
 * If the SVID passed is 2, the user will not be marked registered or requested to ID.
 * This is an addition to accomodate IRCds where we cannot determine this based on the NICK 
 * or UID command. Some IRCd's keep +r on when changing nicks and do not use SVID (ex. InspIRCd 1.2).
 * Instead we get a METADATA command containing the accountname the user was last identified to.
 * Since this is received after the user is introduced to us we should not yet mark the user
 * as identified or ask him to identify. We will mark him as recognized for the time being and let
 * him keep his +r if he has it.
 * It is the responsibility of the protocol module to make sure that this is either invalidated,
 * or changed to identified. ~ Viper
 **/
User *do_nick(const char *source, char *nick, char *username, char *host,
              char *server, char *realname, time_t ts, uint32 svid,
              uint32 ip, char *vhost, char *uid)
{
    User *user = NULL;

    char *tmp = NULL;
    NickAlias *old_na;          /* Old nick rec */
    int nc_changed = 1;         /* Did nick core change? */
    int status = 0;             /* Status to apply */
    char mask[USERMAX + HOSTMAX + 2];
    char *logrealname;
    char *oldnick;

    if (!*source) {
        char ipbuf[16];
        struct in_addr addr;

        if (ircd->nickvhost) {
            if (vhost) {
                if (!strcmp(vhost, "*")) {
                    vhost = NULL;
                    if (debug)
                        alog("debug: new user�with no vhost in NICK command: %s", nick);
                }
            }
        }

        /* This is a new user; create a User structure for it. */
        if (debug)
            alog("debug: new user: %s", nick);

        if (ircd->nickip) {
            addr.s_addr = htonl(ip);
            ntoa(addr, ipbuf, sizeof(ipbuf));
        }


        if (LogUsers) {
        /**
         * Ugly swap routine for Flop's bug :)
         **/
            if (realname) {
                tmp = strchr(realname, '%');
                while (tmp) {
                    *tmp = '-';
                    tmp = strchr(realname, '%');
                }
            }
            logrealname = normalizeBuffer(realname);

        /**
         * End of ugly swap
         **/

            if (ircd->nickvhost) {
                if (ircd->nickip) {
                    alog("LOGUSERS: %s (%s@%s => %s) (%s) [%s] connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, ipbuf, server);
                } else {
                    alog("LOGUSERS: %s (%s@%s => %s) (%s) connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, server);
                }
            } else {
                if (ircd->nickip) {
                    alog("LOGUSERS: %s (%s@%s) (%s) [%s] connected to the network (%s).", nick, username, host, logrealname, ipbuf, server);
                } else {
                    alog("LOGUSERS: %s (%s@%s) (%s) connected to the network (%s).", nick, username, host, logrealname, server);
                }
            }
            Anope_Free(logrealname);
        }

        /* We used to ignore the ~ which a lot of ircd's use to indicate no
         * identd response.  That caused channel bans to break, so now we
         * just take what the server gives us.  People are still encouraged
         * to read the RFCs and stop doing anything to usernames depending
         * on the result of an identd lookup.
         */

        /* First check for AKILLs. */
        /* DONT just return null if its an akill match anymore - yes its more efficent to, however, now that ircd's are
         * starting to use things like E/F lines, we cant be 100% sure the client will be removed from the network :/
         * as such, create a user_struct, and if the client is removed, we'll delete it again when the QUIT notice
         * comes in from the ircd.
         **/
        if (check_akill(nick, username, host, vhost, ipbuf)) {
/*            return NULL; */
        }

/**
 * DefCon AKILL system, if we want to akill all connecting user's here's where to do it
 * then force check_akill again on them...
 **/
        /* don't akill on netmerges -Certus */
        /* don't akill clients introduced by ulines. -Viper */
        if (is_sync(findserver(servlist, server))
            && checkDefCon(DEFCON_AKILL_NEW_CLIENTS) && !is_ulined(server)) {
            strncpy(mask, "*@", 3);
            strncat(mask, host, HOSTMAX);
            alog("DEFCON: adding akill for %s", mask);
            add_akill(NULL, mask, s_OperServ,
                      time(NULL) + dotime(DefConAKILL),
                      DefConAkillReason ? DefConAkillReason :
                      "DEFCON AKILL");
            if (check_akill(nick, username, host, vhost, ipbuf)) {
/*            return NULL; */
            }
        }

        /* SGLINE */
        if (ircd->sgline) {
            if (check_sgline(nick, realname))
                return NULL;
        }

        /* SQLINE */
        if (ircd->sqline) {
            if (check_sqline(nick, 0))
                return NULL;
        }

        /* SZLINE */
        if (ircd->szline && ircd->nickip) {
            if (check_szline(nick, ipbuf))
                return NULL;
        }
        /* Now check for session limits */
        if (LimitSessions && !is_ulined(server)
            && !add_session(nick, host, ipbuf))
            return NULL;

        /* Allocate User structure and fill it in. */
        user = new_user(nick);
        user->username = sstrdup(username);
        user->host = sstrdup(host);
        user->server = findserver(servlist, server);
        user->realname = sstrdup(realname);
        user->timestamp = ts;
        user->my_signon = time(NULL);
        user->chost = vhost ? sstrdup(vhost) : sstrdup(host);
        user->vhost = vhost ? sstrdup(vhost) : sstrdup(host);
        if (uid) {
            user->uid = sstrdup(uid);   /* p10/ts6 stuff */
        } else {
            user->uid = NULL;
        }
        user->vident = sstrdup(username);
        /* We now store the user's ip in the user_ struct,
         * because we will use it in serveral places -- DrStein */
        if (ircd->nickip) {
            user->hostip = sstrdup(ipbuf);
        } else {
            user->hostip = NULL;
        }

        if (svid == 0) {
            display_news(user, NEWS_LOGON);
            display_news(user, NEWS_RANDOM);
        }

        if (svid == 2 && user->na) {
            /* We do not yet know if the user should be identified or not.
             * mark him as recognized for now. 
             * It s up to the protocol module to make sure this either becomes ID'd or
             * is invalidated. ~ Viper */
            if (debug) 
                alog("debug: Marking %s as recognized..", user->nick);
            user->svid = 1;
            user->na->status |= NS_RECOGNIZED;
            nc_changed = 0;
        } else if (svid == ts && user->na) {
            /* Timestamp and svid match, and nick is registered; automagically identify the nick */
            user->svid = svid;
            user->na->status |= NS_IDENTIFIED;
            check_memos(user);
            nc_changed = 0;

            /* Start nick tracking if available */
            if (NSNickTracking)
                nsStartNickTracking(user);

        } else if (svid != 1) {
            /* Resets the svid because it doesn't match */
            user->svid = 1;

            anope_cmd_svid_umode(user->nick, user->timestamp);

        } else {
            user->svid = 1;
        }
        send_event(EVENT_NEWNICK, 1, nick);

    } else {
        /* An old user changing nicks. */
        if (UseTS6 && ircd->ts6)
            user = find_byuid(source);

        if (!user)
            user = finduser(source);

        if (!user) {
            alog("user: NICK from nonexistent nick %s", source);
            return NULL;
        }
        user->isSuperAdmin = 0; /* Dont let people nick change and stay SuperAdmins */
        if (debug)
            alog("debug: %s changes nick to %s", source, nick);

        if (LogUsers) {
            logrealname = normalizeBuffer(user->realname);
            if (ircd->vhost) {
                alog("LOGUSERS: %s (%s@%s => %s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), logrealname, nick, user->server->name);
            } else {
                alog("LOGUSERS: %s (%s@%s) (%s) changed nick to %s (%s).",
                     user->nick, user->username, user->host, logrealname,
                     nick, user->server->name);
            }
            if (logrealname) {
                free(logrealname);
            }
        }

        user->timestamp = ts;

        if (stricmp(nick, user->nick) == 0) {
            /* No need to redo things */
            change_user_nick(user, nick);
            nc_changed = 0;
        } else {
            /* Update this only if nicks aren't the same */
            user->my_signon = time(NULL);

            old_na = user->na;
            if (old_na) {
                if (nick_recognized(user))
                    user->na->last_seen = time(NULL);
                status = old_na->status & NS_TRANSGROUP;
                cancel_user(user);
            }

            oldnick = sstrdup(user->nick);
            change_user_nick(user, nick);

            if ((old_na ? old_na->nc : NULL) ==
                (user->na ? user->na->nc : NULL))
                nc_changed = 0;

            if (!nc_changed && (user->na))
                user->na->status |= status;
            else {
                anope_cmd_nc_change(user);
            }

            send_event(EVENT_CHANGE_NICK, 2, nick, oldnick);
            free(oldnick);
        }

        if (ircd->sqline) {
            if (!is_oper(user) && check_sqline(user->nick, 1))
                return NULL;
        }

    }                           /* if (!*source) */

    /* Check for nick tracking to bypass identification */
    if (NSNickTracking && nsCheckNickTracking(user)) {
        user->na->status |= NS_IDENTIFIED;
        nc_changed = 0;
    }

    if (nc_changed || !nick_recognized(user)) {
        if (validate_user(user))
            check_memos(user);

    } else {
        if (nick_identified(user)) {
            char tsbuf[16];
            user->na->last_seen = time(NULL);

            if (user->na->last_usermask)
                free(user->na->last_usermask);
            user->na->last_usermask =
                smalloc(strlen(common_get_vident(user)) +
                        strlen(common_get_vhost(user)) + 2);
            sprintf(user->na->last_usermask, "%s@%s",
                    common_get_vident(user), common_get_vhost(user));

            snprintf(tsbuf, sizeof(tsbuf), "%lu",
                     (unsigned long int) user->timestamp);
            anope_cmd_svid_umode2(user, tsbuf);

            alog("%s: %s!%s@%s automatically identified for nick %s",
                 s_NickServ, user->nick, user->username,
                 user->host, user->nick);
        }
    }

    /* Bahamut sets -r on every nick changes, so we must test it even if nc_changed == 0 */
    if (ircd->check_nick_id) {
        if (nick_identified(user)) {
            char tsbuf[16];
            snprintf(tsbuf, sizeof(tsbuf), "%lu",
                     (unsigned long int) user->timestamp);
            anope_cmd_svid_umode3(user, tsbuf);
        }
    }

    return user;
}
Exemple #22
0
/**
 * The /cs (un)suspend command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
static int do_suspend(User * u)
{
    ChannelInfo *ci;
    char *chan = strtok(NULL, " ");
    char *reason = strtok(NULL, "");

    Channel *c;

    /* Assumes that permission checking has already been done. */
    if (!chan || (ForceForbidReason && !reason)) {
        syntax_error(s_ChanServ, u, "SUSPEND",
                     (ForceForbidReason ? CHAN_SUSPEND_SYNTAX_REASON :
                      CHAN_SUSPEND_SYNTAX));
        return MOD_CONT;
    }

    if (chan[0] != '#') {
        notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_ERROR);
        return MOD_CONT;
    }
    
    /* Only SUSPEND existing channels, otherwise use FORBID (bug #54) */
    if ((ci = cs_findchan(chan)) == NULL) {
        notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
        return MOD_CONT;
    }

    /* You should not SUSPEND a FORBIDEN channel */
    if (ci->flags & CI_VERBOTEN) {
        notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan);
        return MOD_CONT;
    }

    if (readonly)
        notice_lang(s_ChanServ, u, READ_ONLY_MODE);

    if (ci) {
        ci->flags |= CI_SUSPENDED;
        ci->forbidby = sstrdup(u->nick);
        if (reason)
            ci->forbidreason = sstrdup(reason);

        if ((c = findchan(ci->name))) {
            struct c_userlist *cu, *next;
            char *av[3];

            for (cu = c->users; cu; cu = next) {
                next = cu->next;

                if (is_oper(cu->user))
                    continue;

                av[0] = c->name;
                av[1] = cu->user->nick;
                av[2] = reason ? reason : getstring(cu->user->na, CHAN_SUSPEND_REASON);
                anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]);
                do_kick(s_ChanServ, 3, av);
            }
        }

        if (WallForbid)
            anope_cmd_global(s_ChanServ,
                             "\2%s\2 used SUSPEND on channel \2%s\2",
                             u->nick, ci->name);

        alog("%s: %s set SUSPEND for channel %s", s_ChanServ, u->nick,
             ci->name);
        notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan);
        send_event(EVENT_CHAN_SUSPENDED, 1, chan);
    } else {
        alog("%s: Valid SUSPEND for %s by %s failed", s_ChanServ, ci->name,
             u->nick);
        notice_lang(s_ChanServ, u, CHAN_SUSPEND_FAILED, chan);
    }
    return MOD_CONT;
}