Example #1
0
/**
 * The /ns logout command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_logout(User * u)
{
    char *nick = strtok(NULL, " ");
    char *param = strtok(NULL, " ");
    User *u2;

    if (!is_services_admin(u) && nick) {
        syntax_error(s_NickServ, u, "LOGOUT", NICK_LOGOUT_SYNTAX);
    } else if (!(u2 = (nick ? finduser(nick) : u))) {
        notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
    } else if (!u2->na) {
        if (nick)
            notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
        else
            notice_lang(s_NickServ, u, NICK_NOT_REGISTERED);
    } else if (u2->na->status & NS_VERBOTEN) {
        notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u2->na->nick);
    } else if (!nick && !nick_identified(u)) {
        notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
    } else if (nick && is_services_admin(u2)) {
        notice_lang(s_NickServ, u, NICK_LOGOUT_SERVICESADMIN, nick);
    } else {
        if (nick && param && !stricmp(param, "REVALIDATE")) {
            cancel_user(u2);
            validate_user(u2);
        } else {
            u2->na->status &= ~(NS_IDENTIFIED | NS_RECOGNIZED);
        }

        if (ircd->modeonreg) {
            common_svsmode(u2, ircd->modeonunreg, "1");
        }

        u->isSuperAdmin = 0;    /* Dont let people logout and remain a SuperAdmin */
        alog("%s: %s!%s@%s logged out nickname %s", s_NickServ, u->nick,
             u->username, u->host, u2->nick);

        if (nick)
            notice_lang(s_NickServ, u, NICK_LOGOUT_X_SUCCEEDED, nick);
        else
            notice_lang(s_NickServ, u, NICK_LOGOUT_SUCCEEDED);

        /* Stop nick tracking if enabled */
        if (NSNickTracking)
			/* Shouldn't this be u2? -GD */
            nsStopNickTracking(u);

        /* Clear any timers again */
        if (u->na->nc->flags & NI_KILLPROTECT) {
            del_ns_timeout(u->na, TO_COLLIDE);
        }
		
		/* Send out an event */
		send_event(EVENT_NICK_LOGOUT, 1, u2->nick);
    }
    return MOD_CONT;
}
Example #2
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;
}
Example #3
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");
}