Exemplo n.º 1
0
/**
 * The /ns ghost 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_ghost(User * u)
{
    char *nick = strtok(NULL, " ");
    char *pass = strtok(NULL, " ");
    NickAlias *na;
    User *u2;

    if (!nick) {
        syntax_error(s_NickServ, u, "GHOST", NICK_GHOST_SYNTAX);
    } else if (!(u2 = finduser(nick))) {
        notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
    } else if (!(na = u2->na)) {
        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 (stricmp(nick, u->nick) == 0) {
        notice_lang(s_NickServ, u, NICK_NO_GHOST_SELF);
    } else if (pass) {
        int res = enc_check_password(pass, na->nc->pass);
        if (res == 1) {
            char buf[NICKMAX + 32];
            snprintf(buf, sizeof(buf), "GHOST command used by %s",
                     u->nick);

            send_event(EVENT_NICK_GHOSTED, 3, EVENT_START, u->nick, nick);
            alog("%s: %s!%s@%s used GHOST on %s",
                 s_NickServ, u->nick, u->username, u->host, u2->nick);
            kill_user(s_NickServ, nick, buf);
            notice_lang(s_NickServ, u, NICK_GHOST_KILLED, nick);
            send_event(EVENT_NICK_GHOSTED, 3, EVENT_STOP, u->nick, nick);
        } else {
            notice_lang(s_NickServ, u, ACCESS_DENIED);
            if (res == 0) {
                alog("%s: GHOST: invalid password for %s by %s!%s@%s",
                     s_NickServ, nick, u->nick, u->username, u->host);
                bad_password(u);
            }
        }
    } else {
        if (group_identified(u, na->nc)
            || (!(na->nc->flags & NI_SECURE) && is_on_access(u, na->nc))) {
            char buf[NICKMAX + 32];
            snprintf(buf, sizeof(buf), "GHOST command used by %s",
                     u->nick);

            send_event(EVENT_NICK_GHOSTED, 3, EVENT_START, u->nick, nick);
            alog("%s: %s!%s@%s used GHOST on %s",
                 s_NickServ, u->nick, u->username, u->host, u2->nick);
            kill_user(s_NickServ, nick, buf);
            notice_lang(s_NickServ, u, NICK_GHOST_KILLED, nick);
            send_event(EVENT_NICK_GHOSTED, 3, EVENT_STOP, u->nick, nick);
        } else {
            notice_lang(s_NickServ, u, ACCESS_DENIED);
        }
    }

    return MOD_CONT;
}
Exemplo n.º 2
0
int check_sqline(char *nick, int nick_change)
{
    int i;
    SXLine *sx;
    char reason[300];

    if (sqlines.count == 0)
        return 0;

    for (i = 0; i < sqlines.count; i++) {
        sx = sqlines.list[i];
        if (!sx)
            continue;

        if (ircd->chansqline) {
            if (*sx->mask == '#')
                continue;
        }

        if (match_wild_nocase(sx->mask, nick)) {
            sqline(sx->mask, sx->reason);
            /* We kill nick since s_sqline can't */
            snprintf(reason, sizeof(reason), "Q-Lined: %s", sx->reason);
            kill_user(s_OperServ, nick, reason);
            return 1;
        }
    }

    return 0;
}
Exemplo n.º 3
0
/* P10 does not support logout, so kill the user
 * we can't keep track of which logins are stale and which aren't -- jilles */
static bool asuka_on_logout(user_t *u, const char *account)
{
    return_val_if_fail(u != NULL, false);

    kill_user(NULL, u, "Forcing logout %s -> %s", u->nick, account);
    return true;
}
Exemplo n.º 4
0
int add_session(char *nick, char *host, char *hostip)
{
    Session *session, **list;
    Exception *exception;
    int sessionlimit = 0;

    session = findsession(host);

    if (session) {
        exception = find_hostip_exception(host, hostip);

        if (checkDefCon(DEFCON_REDUCE_SESSION)) {
            sessionlimit =
                exception ? exception->limit : DefConSessionLimit;
        } else {
            sessionlimit = exception ? exception->limit : DefSessionLimit;
        }

        if (sessionlimit != 0 && session->count >= sessionlimit) {
            if (SessionLimitExceeded)
                notice(s_OperServ, nick, SessionLimitExceeded, host);
            if (SessionLimitDetailsLoc)
                notice(s_OperServ, nick, "%s", SessionLimitDetailsLoc);

            /* We don't use kill_user() because a user stucture has not yet
             * been created. Simply kill the user. -TheShadow
             */
            kill_user(s_OperServ, nick, "Session limit exceeded");

            session->hits++;
            if (MaxSessionKill && session->hits >= MaxSessionKill) {
                char akillmask[BUFSIZE];
                snprintf(akillmask, sizeof(akillmask), "*@%s", host);
                add_akill(NULL, akillmask, s_OperServ,
                          time(NULL) + SessionAutoKillExpiry,
                          "Session limit exceeded");
                anope_cmd_global(s_OperServ,
                                 "Added a temporary AKILL for \2%s\2 due to excessive connections",
                                 akillmask);
            }
            return 0;
        } else {
            session->count++;
            return 1;
        }
    }

    nsessions++;
    session = scalloc(sizeof(Session), 1);
    session->host = sstrdup(host);
    list = &sessionlist[HASH(session->host)];
    session->next = *list;
    if (*list)
        (*list)->prev = session;
    *list = session;
    session->count = 1;

    return 1;
}
Exemplo n.º 5
0
static void do_killclones(User * u)
{
	char killreason[NICKMAX + 32];
	char akillreason[] = "Temporary KILLCLONES akill.";
	int count;
	char *clonenick, *clonemask, *akillmask;
	User *cloneuser, *user, *tempuser;

	clonenick = strtok(NULL, " ");
	count = 0;
	
	if (!clonenick) {
		notice_lang(s_OperServ, u, OPER_KILLCLONES_SYNTAX);

	} else if (!(cloneuser = finduser(clonenick))) {
		notice_lang(s_OperServ, u, OPER_KILLCLONES_UNKNOWN_NICK,
		    clonenick);

	} else {
		clonemask = smalloc(strlen(cloneuser->host) + 5);
		sprintf(clonemask, "*!*@%s", cloneuser->host);

		akillmask = smalloc(strlen(cloneuser->host) + 3);
		sprintf(akillmask, "*@%s", strlower(cloneuser->host));

		user = firstuser();

		while (user) {
			if (match_usermask(clonemask, user) != 0) {
				tempuser = nextuser();
				count++;
				snprintf(killreason, sizeof(killreason),
				    "Cloning [%d]", count);
				kill_user(NULL, user->nick, killreason);
				user = tempuser;
			} else {
				user = nextuser();
			}
		}

		add_akill(akillmask, akillreason, u->nick,
		    time(NULL) + (60 * 60 * 6));

		wallops(s_OperServ, "\2%s\2 used KILLCLONES for \2%s\2 "
		    "killing \2%d\2 clones.  A temporary AKILL has been "
		    "added for \2%s\2.", u->nick, clonemask, count,
		    akillmask);

		log("%s: KILLCLONES: %d clone(s) matching %s killed.",
		    s_OperServ, count, clonemask);

		free(akillmask);
		free(clonemask);
	}
}
Exemplo n.º 6
0
static int do_qakill_some_lameass(User * u)
{
    char *to_be_akilled, *reason;
    char reasonx[512];
    char mask[USERMAX + HOSTMAX + 2];
    User *target;

    to_be_akilled = strtok(NULL, " ");
    reason = strtok(NULL, "");

    if (!is_services_admin(u)) { 
        notice(s_OperServ, u->nick, "Access Denied");
	return MOD_STOP;
    }
    if (to_be_akilled) {
       if (!reason) {
           reason = "You have been AKILLED";
       }
       if (AddAkiller) {
           snprintf(reasonx, sizeof(reasonx), "[%s] %s", u->nick, reason);
       }
       if ((target = finduser(to_be_akilled))) {
            sprintf(mask, "*@%s", target->host);
            #ifdef DISABLE_LOWER_QAKILL
            if ((is_services_admin(target)) && (!is_services_root(u))) {
               notice(s_OperServ, u->nick, "Permission Denied");
               #ifndef ANOPE17x
	       wallops(s_OperServ, "%s attempted to QAKILL %s (%s)", u->nick, target->nick, reasonx);
               #else
	       anope_cmd_global(s_OperServ, "%s attempted to QAKILL %s (%s)", u->nick, target->nick, reasonx);
               #endif
               return MOD_STOP;
	    }
            #endif
            add_akill(u, mask, u->nick, time(NULL)+AutokillExpiry, reason);
            if (WallOSAkill) {
                #ifndef ANOPE17x
                wallops(s_OperServ, "%s used QAKILL on %s (%s)", u->nick, target->nick, reasonx);
                #else
                anope_cmd_global(s_OperServ, "%s used QAKILL on %s (%s)", u->nick, target->nick, reasonx);
                #endif
            }
	    if (!AkillOnAdd) {
                kill_user(s_OperServ, target->nick, reasonx);
	    }
       }
       else {
            notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, to_be_akilled);
       }
    } 
    else {
          notice(s_OperServ, u->nick, "See /msg OperServ HELP QAKILL for more info.");
    }
    return MOD_CONT;
}
Exemplo n.º 7
0
int check_akill(char *nick, const char *username, const char *host,
                const char *vhost, const char *ip)
{
    int i;
    Akill *ak;

    /**
     * If DefCon is set to NO new users - kill the user ;).
     **/
    if (checkDefCon(DEFCON_NO_NEW_CLIENTS)) {
        kill_user(s_OperServ, nick, DefConAkillReason);
        return 1;
    }

    if (akills.count == 0)
        return 0;

    for (i = 0; i < akills.count; i++) {
        ak = akills.list[i];
        if (!ak)
            continue;
        if (match_wild_nocase(ak->user, username)
            && match_wild_nocase(ak->host, host)) {
            xanadu_cmd_akill(ak->user, ak->host, ak->by, ak->seton,
                            ak->expires, ak->reason);
            return 1;
        }
        if (ircd->vhost) {
            if (vhost) {
                if (match_wild_nocase(ak->user, username)
                    && match_wild_nocase(ak->host, vhost)) {
                    xanadu_cmd_akill(ak->user, ak->host, ak->by, ak->seton,
                                    ak->expires, ak->reason);
                    return 1;
                }
            }
        }
        if (ircd->nickip) {
            if (ip) {
                if (match_wild_nocase(ak->user, username)
                    && match_wild_nocase(ak->host, ip)) {
                    xanadu_cmd_akill(ak->user, ak->host, ak->by, ak->seton,
                                    ak->expires, ak->reason);
                    return 1;
                }
            }
        }

    }

    return 0;
}
Exemplo n.º 8
0
/* P10 does not support logout, so kill the user
 * we can't keep track of which logins are stale and which aren't -- jilles */
static bool asuka_on_logout(user_t *u, const char *account)
{
	if (!me.connected)
		return false;

	if (u != NULL)
	{
		kill_user(NULL, u, "Forcing logout %s -> %s", u->nick, account);
		return true;
	}
	else
		return false;
}
Exemplo n.º 9
0
/**
 * Note a bad password attempt for the given user.  If they've used up
 * their limit, toss them off.
 * @param u the User to check
 * @return void
 */
void bad_password(User * u)
{
    time_t now = time(NULL);

    if (!u || !BadPassLimit) {
        return;
    }

    if (BadPassTimeout > 0 && u->invalid_pw_time > 0
        && u->invalid_pw_time < now - BadPassTimeout)
        u->invalid_pw_count = 0;
    u->invalid_pw_count++;
    u->invalid_pw_time = now;
    if (u->invalid_pw_count >= BadPassLimit) {
        kill_user(NULL, u->nick, "Too many invalid passwords");
    }
}
Exemplo n.º 10
0
/*
 * Handle reporting for both fantasy commands and normal commands in GameServ
 * quickly and easily. Of course, sourceinfo has a vtable that can be manipulated,
 * but this is quicker and easier...                                  -- nenolod
 */
static void gs_command_report(sourceinfo_t *si, const char *fmt, ...)
{
	va_list args;
	char buf[BUFSIZE];

	va_start(args, fmt);
	vsnprintf(buf, BUFSIZE, fmt, args);
	va_end(args);

	if (si->c != NULL)
		msg(chansvs.nick, si->c->name, "%s", buf);
	else
		command_success_nodata(si, "%s", buf);

	if (!strcasecmp(buf, "*BANG*"))
		kill_user(si->service->me, si->su, "Lost at Russian Roulette.");
}
Exemplo n.º 11
0
/**
	@brief		Exe_Builtin Ό³Έν
				OPERATED MMC COMMAND IN MMCD
	@param		mml_msg
	@param		sockfd
	@param		In_Arg
*/
int Exe_Builtin(mml_msg *ml, int sockfd, In_Arg  in_para[])
{
	log_print(LOGN_INFO, "sockfd[%d] MSG_ID[%d]", sockfd, ml->msg_id );

	switch(ml->msg_id) {

		case MI_USER_LOGIN:
			usr_login(&in_para[0], sockfd, ml);
			break;

		case MI_USER_LOGOUT:
			usr_logout(&in_para[0], sockfd, ml);
			fflush(stdout);
			break;

		case MI_KILL_USER:
			kill_user(&in_para[0], sockfd, ml);
			fflush(stdout);
            break;

		/* needed test by uamyd 2008.01.08 */
		case MI_DIS_HIS_CMD:
			dis_his_cmd(&in_para[0], sockfd, ml);
			break;

		case MI_DIS_CMD_EXE:
			dis_cmd_exe(&in_para[0], sockfd, ml);
			break;
	
		case MI_DEL_CMD_EXE:
            del_cmd_exe(&in_para[0], sockfd, ml);
            break;

        case MI_GET_COM:
            dGetCOMString(&in_para[0], sockfd, ml);
            break;
	
		default :
			break;
	}
	return 1;
}
Exemplo n.º 12
0
void ns_cmd_regain(sourceinfo_t *si, int parc, char *parv[])
{
	myuser_t *mu;
	char *target = parv[0];
	char *password = parv[1];
	user_t *target_u;
	mynick_t *mn;

	if (si->su == NULL)
	{
		command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "REGAIN");
		return;
	}

	if (!target)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGAIN");
		command_fail(si, fault_needmoreparams, _("Syntax: REGAIN <target> [password]"));
		return;
	}

	if (nicksvs.no_nick_ownership)
		mn = NULL, mu = myuser_find(target);
	else
	{
		mn = mynick_find(target);
		mu = mn != NULL ? mn->owner : NULL;
	}
	target_u = user_find_named(target);
	if (!mu)
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not a registered nickname."), target);
		return;
	}

	if (!target_u)
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), target);
		return;
	}
	else if (target_u == si->su)
	{
		command_fail(si, fault_badparams, _("You may not ghost yourself."));
		return;
	}

	if ((!nicksvs.no_nick_ownership && mn && mu == si->smu) || /* we're identified under their nick's account */
			(!nicksvs.no_nick_ownership && password && mn && verify_password(mu, password))) /* we have their nick's password */
	{
		logcommand(si, CMDLOG_DO, "REGAIN %s!%s@%s", target_u->nick, target_u->user, target_u->vhost);

		kill_user(si->service->me, target_u, "REGAIN command used by %s",
				si->su != NULL && !strcmp(si->su->user, target_u->user) && !strcmp(si->su->vhost, target_u->vhost) ? si->su->nick : get_source_mask(si));

		command_success_nodata(si, _("\2%s\2 has been regained."), target);
		fnc_sts(si->service->me, si->su, target, FNC_REGAIN);

		/* don't update the nick's last seen time */
		mu->lastlogin = CURRTIME;

		return;
	}

	if (password && mu)
	{
		logcommand(si, CMDLOG_DO, "failed REGAIN %s (bad password)", target);
		command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), mu->name);
	}
	else
	{
		logcommand(si, CMDLOG_DO, "failed REGAIN %s (invalid login)", target);
		command_fail(si, fault_noprivs, _("You may not regain \2%s\2."), target);
	}
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
void ns_cmd_ghost(sourceinfo_t *si, int parc, char *parv[])
{
	myuser_t *mu;
	char *target = parv[0];
	char *password = parv[1];
	user_t *target_u;
	mynick_t *mn;

	if (!target)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "GHOST");
		command_fail(si, fault_needmoreparams, _("Syntax: GHOST <target> [password]"));
		return;
	}

	if (nicksvs.no_nick_ownership)
		mn = NULL, mu = myuser_find(target);
	else
	{
		mn = mynick_find(target);
		mu = mn != NULL ? mn->owner : NULL;
	}

	target_u = user_find_named(target);
	if (!target_u)
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), target);
		return;
	}
	else if (!mu && !target_u->myuser)
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not a registered nickname."), target);
		return;
	}
	else if (target_u == si->su)
	{
		command_fail(si, fault_badparams, _("You may not ghost yourself."));
		return;
	}

	/* At this point, we're now checking metadata associated with the target's account.
	 * If the target nick is unregistered, mu will be unset thus far. */
	if (target_u->myuser && !mu)
		mu = target_u->myuser;

	if (password && metadata_find(mu, "private:freeze:freezer"))
	{
		command_fail(si, fault_authfail, "You cannot ghost users as \2%s\2 because the account has been frozen.", entity(mu)->name);
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (frozen)", target);
		return;
	}

	if (password && (mu->flags & MU_NOPASSWORD))
	{
		command_fail(si, fault_authfail, _("Password authentication is disabled for this account."));
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (password authentication disabled)", target);
		return;
	}

	if ((target_u->myuser && target_u->myuser == si->smu) || /* they're identified under our account */
			(!nicksvs.no_nick_ownership && mn && mu == si->smu) || /* we're identified under their nick's account */
			(!nicksvs.no_nick_ownership && password && verify_password(mu, password))) /* we have the correct password */
	{
		logcommand(si, CMDLOG_DO, "GHOST: \2%s!%s@%s\2", target_u->nick, target_u->user, target_u->vhost);

		kill_user(si->service->me, target_u, "GHOST command used by %s",
				si->su != NULL && !strcmp(si->su->user, target_u->user) && !strcmp(si->su->vhost, target_u->vhost) ? si->su->nick : get_source_mask(si));

		command_success_nodata(si, _("\2%s\2 has been ghosted."), target);

		/* Update the account's last seen time.
		 * Perhaps the ghosted nick belonged to someone else, but we were identified to it?
		 * Try this first. */
		if (target_u->myuser && target_u->myuser == si->smu)
			target_u->myuser->lastlogin = CURRTIME;
		else
			mu->lastlogin = CURRTIME;

		return;
	}

	if (password)
	{
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (bad password)", target);
		command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), entity(mu)->name);
		bad_password(si, mu);
	}
	else
	{
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (invalid login)", target);
		command_fail(si, fault_noprivs, _("You may not ghost \2%s\2."), target);
	}
}
Exemplo n.º 15
0
void ns_cmd_ghost(sourceinfo_t *si, int parc, char *parv[])
{
	myuser_t *mu;
	char *target = parv[0];
	char *password = parv[1];
	user_t *target_u;
	mynick_t *mn;

	if (!target)
	{
		command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "GHOST");
		command_fail(si, fault_needmoreparams, _("Syntax: GHOST <target> [password]"));
		return;
	}

	if (nicksvs.no_nick_ownership)
		mn = NULL, mu = myuser_find(target);
	else
	{
		mn = mynick_find(target);
		mu = mn != NULL ? mn->owner : NULL;
	}
	target_u = user_find_named(target);
	if (!mu && (!target_u || !target_u->myuser))
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not a registered nickname."), target);
		return;
	}

	if (!target_u)
	{
		command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), target);
		return;
	}
	else if (target_u == si->su)
	{
		command_fail(si, fault_badparams, _("You may not ghost yourself."));
		return;
	}

	if (password && metadata_find(mu, "private:freeze:freezer"))
	{
		command_fail(si, fault_authfail, "You cannot ghost users as \2%s\2 because the account has been frozen.", entity(mu)->name);
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (frozen)", target);
		return;
	}

	if ((target_u->myuser && target_u->myuser == si->smu) || /* they're identified under our account */
			(!nicksvs.no_nick_ownership && mn && mu == si->smu) || /* we're identified under their nick's account */
			(!nicksvs.no_nick_ownership && password && mn && verify_password(mu, password))) /* we have their nick's password */
	{
		/* If we're ghosting an unregistered nick, mu will be unset,
		 * however if it _is_ registered, we still need to set it or
		 * the wrong user will have their last seen time updated... */
		if(target_u->myuser && target_u->myuser == si->smu)
			mu = target_u->myuser;

		logcommand(si, CMDLOG_DO, "GHOST: \2%s!%s@%s\2", target_u->nick, target_u->user, target_u->vhost);

		kill_user(si->service->me, target_u, "GHOST command used by %s",
				si->su != NULL && !strcmp(si->su->user, target_u->user) && !strcmp(si->su->vhost, target_u->vhost) ? si->su->nick : get_source_mask(si));

		command_success_nodata(si, _("\2%s\2 has been ghosted."), target);

		/* don't update the nick's last seen time */
		mu->lastlogin = CURRTIME;

		return;
	}

	if (password && mu)
	{
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (bad password)", target);
		command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), entity(mu)->name);
		bad_password(si, mu);
	}
	else
	{
		logcommand(si, CMDLOG_DO, "failed GHOST \2%s\2 (invalid login)", target);
		command_fail(si, fault_noprivs, _("You may not ghost \2%s\2."), target);
	}
}