/* send_linebuf_remote() * * inputs - client to attach to, sender, linebuf * outputs - * side effects - client has linebuf attached */ static void send_linebuf_remote(struct Client *to, struct Client *from, buf_head_t *linebuf) { if(to->from) to = to->from; /* test for fake direction */ if(!MyClient(from) && IsPerson(to) && (to == from->from)) { if(IsServer(from)) { sendto_realops_flags(UMODE_ALL, L_ALL, "Send message to %s[%s] dropped from %s(Fake Dir)", to->name, to->from->name, from->name); return; } sendto_realops_flags(UMODE_ALL, L_ALL, "Ghosted: %s[%s@%s] from %s[%s@%s] (%s)", to->name, to->username, to->host, from->name, from->username, from->host, to->from->name); kill_client_serv_butone(NULL, to, "%s (%s[%s@%s] Ghosted %s)", me.name, to->name, to->username, to->host, to->from->name); to->flags |= FLAGS_KILLED; exit_client(NULL, to, &me, "Ghosted client"); return; } _send_linebuf(to, linebuf); return; }
/* * check_clean_nick() * * input - pointer to source * - nickname * - truncated nickname * - origin of client * output - none * side effects - if nickname is erroneous, or a different length to * truncated nickname, return 1 */ static int check_clean_nick(struct Client *client_p, struct Client *source_p, char *nick, char *newnick, char *server) { /* the old code did some wacky stuff here, if the nick is invalid, kill it * and dont bother messing at all */ /* * Zero length nicks are bad too..this shouldn't happen but.. */ if(!clean_nick_name(nick) || strcmp(nick, newnick) || nick[0] == '\0') { ServerStats->is_kill++; sendto_realops_flags(UMODE_DEBUG, L_ALL, "Bad Nick: %s From: %s(via %s)", nick, server, client_p->name); sendto_one(client_p, ":%s KILL %s :%s (Bad Nickname)", me.name, newnick, me.name); /* bad nick change */ if(source_p != client_p) { kill_client_serv_butone(client_p, source_p, "%s (Bad Nickname)", me.name); source_p->flags |= FLAGS_KILLED; exit_client(client_p, source_p, &me, "Bad Nickname"); } return 1; } return 0; }
static int ms_signon(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; int newts, sameuser; char login[NICKLEN+1]; if(!clean_nick(parv[1])) { ServerStats.is_kill++; sendto_realops_snomask(SNO_DEBUG, L_ALL, "Bad Nick from SIGNON: %s From: %s(via %s)", parv[1], source_p->servptr->name, client_p->name); /* if source_p has an id, kill_client_serv_butone() will * send a kill to client_p, otherwise do it here */ if (!has_id(source_p)) sendto_one(client_p, ":%s KILL %s :%s (Bad nickname from SIGNON)", get_id(&me, client_p), parv[1], me.name); kill_client_serv_butone(client_p, source_p, "%s (Bad nickname from SIGNON)", me.name); source_p->flags |= FLAGS_KILLED; exit_client(NULL, source_p, &me, "Bad nickname from SIGNON"); return 0; } if(!clean_username(parv[2]) || !clean_host(parv[3])) { ServerStats.is_kill++; sendto_realops_snomask(SNO_DEBUG, L_ALL, "Bad user@host from SIGNON: %s@%s From: %s(via %s)", parv[2], parv[3], source_p->servptr->name, client_p->name); /* if source_p has an id, kill_client_serv_butone() will * send a kill to client_p, otherwise do it here */ if (!has_id(source_p)) sendto_one(client_p, ":%s KILL %s :%s (Bad user@host from SIGNON)", get_id(&me, client_p), parv[1], me.name); kill_client_serv_butone(client_p, source_p, "%s (Bad user@host from SIGNON)", me.name); source_p->flags |= FLAGS_KILLED; exit_client(NULL, source_p, &me, "Bad user@host from SIGNON"); return 0; } newts = atol(parv[4]); if(!strcmp(parv[5], "0")) login[0] = '\0'; else if(*parv[5] != '*') { if (clean_nick(parv[5])) rb_strlcpy(login, parv[5], NICKLEN + 1); else return 0; } target_p = find_named_client(parv[1]); if(target_p != NULL && target_p != source_p) { /* In case of collision, follow NICK rules. */ /* XXX this is duplicated code and does not do SAVE */ if(IsUnknown(target_p)) exit_client(NULL, target_p, &me, "Overridden"); else { if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Nick change collision from SIGNON from %s to %s(%s <- %s)(both killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); ServerStats.is_kill++; sendto_one_numeric(target_p, ERR_NICKCOLLISION, form_str(ERR_NICKCOLLISION), target_p->name); kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name); ServerStats.is_kill++; kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name); target_p->flags |= FLAGS_KILLED; exit_client(NULL, target_p, &me, "Nick collision(new)"); source_p->flags |= FLAGS_KILLED; exit_client(client_p, source_p, &me, "Nick collision(old)"); return 0; } else { sameuser = !irccmp(target_p->username, source_p->username) && !irccmp(target_p->host, source_p->host); if((sameuser && newts < target_p->tsinfo) || (!sameuser && newts > target_p->tsinfo)) { if(sameuser) sendto_realops_snomask(SNO_GENERAL, L_ALL, "Nick change collision from SIGNON from %s to %s(%s <- %s)(older killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); else sendto_realops_snomask(SNO_GENERAL, L_ALL, "Nick change collision from SIGNON from %s to %s(%s <- %s)(newer killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); ServerStats.is_kill++; sendto_one_numeric(target_p, ERR_NICKCOLLISION, form_str(ERR_NICKCOLLISION), target_p->name); /* kill the client issuing the nickchange */ kill_client_serv_butone(client_p, source_p, "%s (Nick change collision)", me.name); source_p->flags |= FLAGS_KILLED; if(sameuser) exit_client(client_p, source_p, &me, "Nick collision(old)"); else exit_client(client_p, source_p, &me, "Nick collision(new)"); return 0; } else { if(sameuser) sendto_realops_snomask(SNO_GENERAL, L_ALL, "Nick collision from SIGNON on %s(%s <- %s)(older killed)", target_p->name, target_p->from->name, client_p->name); else sendto_realops_snomask(SNO_GENERAL, L_ALL, "Nick collision from SIGNON on %s(%s <- %s)(newer killed)", target_p->name, target_p->from->name, client_p->name); sendto_one_numeric(target_p, ERR_NICKCOLLISION, form_str(ERR_NICKCOLLISION), target_p->name); /* kill the client who existed before hand */ kill_client_serv_butone(client_p, target_p, "%s (Nick collision)", me.name); ServerStats.is_kill++; target_p->flags |= FLAGS_KILLED; (void) exit_client(client_p, target_p, &me, "Nick collision"); } } } } send_signon(client_p, source_p, parv[1], parv[2], parv[3], newts, login); return 0; }
static int me_svslogin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p, *exist_p; char nick[NICKLEN+1], login[NICKLEN+1]; char user[USERLEN+1], host[HOSTLEN+1]; int valid = 0; if(!(source_p->flags & FLAGS_SERVICE)) return 0; if((target_p = find_client(parv[1])) == NULL) return 0; if(!MyClient(target_p) && !IsUnknown(target_p)) return 0; if(clean_nick(parv[2])) { rb_strlcpy(nick, parv[2], NICKLEN + 1); valid |= NICK_VALID; } else if(*target_p->name) rb_strlcpy(nick, target_p->name, NICKLEN + 1); else strcpy(nick, "*"); if(clean_username(parv[3])) { rb_strlcpy(user, parv[3], USERLEN + 1); valid |= USER_VALID; } else rb_strlcpy(user, target_p->username, USERLEN + 1); if(clean_host(parv[4])) { rb_strlcpy(host, parv[4], HOSTLEN + 1); valid |= HOST_VALID; } else rb_strlcpy(host, target_p->host, HOSTLEN + 1); if(*parv[5] == '*') { if(target_p->user) rb_strlcpy(login, target_p->user->suser, NICKLEN + 1); else login[0] = '\0'; } else if(!strcmp(parv[5], "0")) login[0] = '\0'; else rb_strlcpy(login, parv[5], NICKLEN + 1); /* Login (mostly) follows nick rules. */ if(*login && !clean_nick(login)) return 0; if((exist_p = find_person(nick)) && target_p != exist_p) { char buf[BUFSIZE]; if(MyClient(exist_p)) sendto_one(exist_p, ":%s KILL %s :(Nickname regained by services)", me.name, exist_p->name); exist_p->flags |= FLAGS_KILLED; kill_client_serv_butone(NULL, exist_p, "%s (Nickname regained by services)", me.name); rb_snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", me.name); exit_client(NULL, exist_p, &me, buf); } else if((exist_p = find_client(nick)) && IsUnknown(exist_p) && exist_p != target_p) { exit_client(NULL, exist_p, &me, "Overridden"); } if(*login) { /* Strip leading digits, unless it's purely numeric. */ const char *p = login; while(IsDigit(*p)) p++; if(!*p) p = login; sendto_one(target_p, form_str(RPL_LOGGEDIN), me.name, EmptyString(target_p->name) ? "*" : target_p->name, nick, user, host, p, p); } else sendto_one(target_p, form_str(RPL_LOGGEDOUT), me.name, EmptyString(target_p->name) ? "*" : target_p->name, nick, user, host); if(IsUnknown(target_p)) { struct User *user_p = make_user(target_p); if(valid & NICK_VALID) strcpy(target_p->preClient->spoofnick, nick); if(valid & USER_VALID) strcpy(target_p->preClient->spoofuser, user); if(valid & HOST_VALID) strcpy(target_p->preClient->spoofhost, host); rb_strlcpy(user_p->suser, login, NICKLEN + 1); } else { char note[NICKLEN + 10]; send_signon(NULL, target_p, nick, user, host, rb_current_time(), login); rb_snprintf(note, NICKLEN + 10, "Nick: %s", target_p->name); rb_note(target_p->localClient->F, note); } return 0; }
static int perform_nick_collides(struct Client *source_p, struct Client *client_p, struct Client *target_p, int parc, char *parv[], time_t newts, char *nick) { int sameuser; /* server introducing new nick */ if(IsServer(source_p)) { /* if we dont have a ts, or their TS's are the same, kill both */ if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo)) { sendto_realops_flags(UMODE_ALL, L_ALL, "Nick collision on %s(%s <- %s)(both killed)", target_p->name, target_p->from->name, client_p->name); kill_client_serv_butone(NULL, target_p, "%s (Nick collision (new))", me.name); ServerStats->is_kill++; sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name, target_p->name, target_p->name); target_p->flags |= FLAGS_KILLED; exit_client(client_p, target_p, &me, "Nick collision (new)"); return 0; } /* the timestamps are different */ else { sameuser = (target_p->user) && !irccmp(target_p->username, parv[5]) && !irccmp(target_p->host, parv[6]); /* if the users are the same (loaded a client on a different server) * and the new users ts is older, or the users are different and the * new users ts is newer, ignore the new client and let it do the kill */ if((sameuser && newts < target_p->tsinfo) || (!sameuser && newts > target_p->tsinfo)) { return 0; } else { if(sameuser) sendto_realops_flags(UMODE_ALL, L_ALL, "Nick collision on %s(%s <- %s)(older killed)", target_p->name, target_p->from->name, client_p->name); else sendto_realops_flags(UMODE_ALL, L_ALL, "Nick collision on %s(%s <- %s)(newer killed)", target_p->name, target_p->from->name, client_p->name); ServerStats->is_kill++; sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name, target_p->name, target_p->name); /* if it came from a LL server, itd have been source_p, * so we dont need to mark target_p as known */ kill_client_serv_butone(source_p, target_p, "%s (Nick collision (new))", me.name); target_p->flags |= FLAGS_KILLED; (void) exit_client(client_p, target_p, &me, "Nick collision"); nick_from_server(client_p, source_p, parc, parv, newts, nick); return 0; } } } /* its a client changing nick and causing a collide */ if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user) { sendto_realops_flags(UMODE_ALL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(both killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); ServerStats->is_kill++; sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name, target_p->name, target_p->name); /* if we got the message from a LL, it knows about source_p */ kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name); ServerStats->is_kill++; kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name); target_p->flags |= FLAGS_KILLED; exit_client(NULL, target_p, &me, "Nick collision(new)"); source_p->flags |= FLAGS_KILLED; exit_client(client_p, source_p, &me, "Nick collision(old)"); return 0; } else { sameuser = !irccmp(target_p->username, source_p->username) && !irccmp(target_p->host, source_p->host); if((sameuser && newts < target_p->tsinfo) || (!sameuser && newts > target_p->tsinfo)) { if(sameuser) sendto_realops_flags(UMODE_ALL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(older killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); else sendto_realops_flags(UMODE_ALL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(newer killed)", source_p->name, target_p->name, target_p->from->name, client_p->name); ServerStats->is_kill++; /* this won't go back to the incoming link, so LL doesnt matter */ kill_client_serv_butone(client_p, source_p, "%s (Nick change collision)", me.name); source_p->flags |= FLAGS_KILLED; if(sameuser) exit_client(client_p, source_p, &me, "Nick collision(old)"); else exit_client(client_p, source_p, &me, "Nick collision(new)"); return 0; } else { if(sameuser) sendto_realops_flags(UMODE_ALL, L_ALL, "Nick collision on %s(%s <- %s)(older killed)", target_p->name, target_p->from->name, client_p->name); else sendto_realops_flags(UMODE_ALL, L_ALL, "Nick collision on %s(%s <- %s)(newer killed)", target_p->name, target_p->from->name, client_p->name); kill_client_serv_butone(source_p, target_p, "%s (Nick collision)", me.name); ServerStats->is_kill++; sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name, target_p->name, target_p->name); target_p->flags |= FLAGS_KILLED; (void) exit_client(client_p, target_p, &me, "Nick collision"); } } /* we should only ever call nick_from_server() here, as * this is a client changing nick, not a new client */ nick_from_server(client_p, source_p, parc, parv, newts, nick); return 0; }