X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/d38d07f03037fc4842901ed8c11eb905b15b53c9..2a17ae5483b7456162dd503e0593e8381eaa1084:/modules/core/m_nick.c diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index 2f583ea6..b9ed03fc 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -47,6 +47,7 @@ #include "scache.h" #include "s_newconf.h" #include "monitor.h" +#include "s_assert.h" /* Give all UID nicks the same TS. This ensures nick TS is always the same on * all servers for each nick-user pair, also if a user with a UID nick changes @@ -68,7 +69,7 @@ static void bad_nickname(struct Client *, const char *); struct Message nick_msgtab = { "NICK", 0, 0, 0, MFLG_SLOW, - {{mr_nick, 0}, {m_nick, 0}, {mc_nick, 3}, {ms_nick, 8}, mg_ignore, {m_nick, 0}} + {{mr_nick, 0}, {m_nick, 0}, {mc_nick, 3}, {ms_nick, 0}, mg_ignore, {m_nick, 0}} }; struct Message uid_msgtab = { "UID", 0, 0, 0, MFLG_SLOW, @@ -94,7 +95,7 @@ static int change_remote_nick(struct Client *, struct Client *, time_t, static int clean_nick(const char *, int loc_client); static int clean_username(const char *); static int clean_host(const char *); -static int clean_uid(const char *uid); +static int clean_uid(const char *uid, const char *sid); static void set_initial_nick(struct Client *client_p, struct Client *source_p, char *nick); static void change_local_nick(struct Client *client_p, struct Client *source_p, char *nick, int); @@ -108,7 +109,6 @@ static int perform_nickchange_collides(struct Client *, struct Client *, struct Client *, int, const char **, time_t, const char *); /* mr_nick() - * parv[0] = sender prefix * parv[1] = nickname */ static int @@ -116,7 +116,6 @@ mr_nick(struct Client *client_p, struct Client *source_p, int parc, const char * { struct Client *target_p; char nick[NICKLEN]; - char *s; if (strlen(client_p->id) == 3) { @@ -124,28 +123,21 @@ mr_nick(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; } - if(parc < 2 || EmptyString(parv[1]) || (parv[1][0] == '~')) + if(parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, EmptyString(source_p->name) ? "*" : source_p->name); return 0; } - /* due to the scandinavian origins, (~ being uppercase of ^) and ~ - * being disallowed as a nick char, we need to chop the first ~ - * instead of just erroring. - */ - if((s = strchr(parv[1], '~'))) - *s = '\0'; - /* copy the nick and terminate it */ - rb_strlcpy(nick, parv[1], sizeof(nick)); + rb_strlcpy(nick, parv[1], ConfigFileEntry.nicklen); /* check the nickname is ok */ if(!clean_nick(nick, 1)) { sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), - me.name, EmptyString(parv[0]) ? "*" : parv[0], parv[1]); + me.name, EmptyString(source_p->name) ? "*" : source_p->name, parv[1]); return 0; } @@ -175,7 +167,6 @@ mr_nick(struct Client *client_p, struct Client *source_p, int parc, const char * } /* m_nick() - * parv[0] = sender prefix * parv[1] = nickname */ static int @@ -183,32 +174,24 @@ m_nick(struct Client *client_p, struct Client *source_p, int parc, const char *p { struct Client *target_p; char nick[NICKLEN]; - char *s; - if(parc < 2 || EmptyString(parv[1]) || (parv[1][0] == '~')) + if(parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, source_p->name); return 0; } - /* due to the scandinavian origins, (~ being uppercase of ^) and ~ - * being disallowed as a nick char, we need to chop the first ~ - * instead of just erroring. - */ - if((s = strchr(parv[1], '~'))) - *s = '\0'; - /* mark end of grace period, to prevent nickflooding */ if(!IsFloodDone(source_p)) flood_endgrace(source_p); /* terminate nick to NICKLEN, we dont want clean_nick() to error! */ - rb_strlcpy(nick, parv[1], sizeof(nick)); + rb_strlcpy(nick, parv[1], ConfigFileEntry.nicklen); /* check the nickname is ok */ if(!clean_nick(nick, 1)) { - sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], nick); + sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick); return 0; } @@ -245,7 +228,7 @@ m_nick(struct Client *client_p, struct Client *source_p, int parc, const char *p change_local_nick(client_p, source_p, nick, 1); } else - sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, parv[0], nick); + sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, source_p->name, nick); return 0; } @@ -255,23 +238,11 @@ m_nick(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } -/* ms_nick() - * +/* mc_nick() + * * server -> server nick change - * parv[0] = sender prefix * parv[1] = nickname * parv[2] = TS when nick change - * - * server introducing new nick - * parv[0] = sender prefix - * parv[1] = nickname - * parv[2] = hop count - * parv[3] = TS - * parv[4] = umode - * parv[5] = username - * parv[6] = hostname - * parv[7] = server - * parv[8] = ircname */ static int mc_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) @@ -316,74 +287,21 @@ mc_nick(struct Client *client_p, struct Client *source_p, int parc, const char * static int ms_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - struct Client *target_p; - time_t newts = 0; + const char *nick, *server; - if(parc != 9) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Dropping server %s due to (invalid) command 'NICK' " - "with %d arguments (expecting 9)", client_p->name, parc); - ilog(L_SERVER, "Excess parameters (%d) for command 'NICK' from %s.", - parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to NICK command"); - return 0; - } - - /* if nicks empty, erroneous, or too long, kill */ - if(!clean_nick(parv[1], 0)) - { - bad_nickname(client_p, parv[1]); - return 0; - } + nick = parc > 1 ? parv[1] : "?"; + server = parc > 7 ? parv[7] : "?"; - /* invalid username or host? */ - if(!clean_username(parv[5]) || !clean_host(parv[6])) - { - ServerStats.is_kill++; - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad user@host: %s@%s From: %s(via %s)", - parv[5], parv[6], parv[7], client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.name, parv[1], me.name); - return 0; - } - - /* check the length of the clients gecos */ - if(strlen(parv[8]) > REALLEN) - { - char *s = LOCAL_COPY(parv[8]); - /* why exactly do we care? --fl */ - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Long realname from server %s for %s", parv[7], parv[1]); - - s[REALLEN] = '\0'; - parv[8] = s; - } - - newts = atol(parv[3]); - - target_p = find_named_client(parv[1]); + sendto_wallops_flags(UMODE_WALLOP, &me, + "Link %s cancelled, TS5 nickname %s on %s introduced (old server?)", + client_p->name, nick, server); + sendto_server(NULL, NULL, CAP_TS6, NOCAPS, + ":%s WALLOPS :Link %s cancelled, TS5 nickname %s on %s introduced (old server?)", + me.id, client_p->name, nick, server); + ilog(L_SERVER, "Link %s cancelled, TS5 nickname %s on %s introduced (old server?)", + client_p->name, nick, server); - /* if the nick doesnt exist, allow it and process like normal */ - if(target_p == NULL) - { - register_client(client_p, NULL, parv[1], newts, parc, parv); - } - else if(IsUnknown(target_p)) - { - exit_client(NULL, target_p, &me, "Overridden"); - register_client(client_p, NULL, parv[1], newts, parc, parv); - } - else if(target_p == source_p) - { - /* client changing case of nick */ - if(strcmp(target_p->name, parv[1])) - register_client(client_p, NULL, parv[1], newts, parc, parv); - } - /* we've got a collision! */ - else - perform_nick_collides(source_p, client_p, target_p, parc, parv, - newts, parv[1], NULL); + exit_client(client_p, client_p, &me, "TS5 nickname introduced"); return 0; } @@ -404,6 +322,7 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p { struct Client *target_p; time_t newts = 0; + char squitreason[120]; newts = atol(parv[3]); @@ -414,7 +333,10 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p "with %d arguments (expecting 10)", client_p->name, parc); ilog(L_SERVER, "Excess parameters (%d) for command 'UID' from %s.", parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to UID command"); + rb_snprintf(squitreason, sizeof squitreason, + "Excess parameters (%d) to %s command, expecting %d", + parc, "UID", 10); + exit_client(client_p, client_p, client_p, squitreason); return 0; } @@ -425,23 +347,22 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p return 0; } - if(!clean_username(parv[5]) || !clean_host(parv[6])) + if(!clean_uid(parv[8], source_p->id)) { - ServerStats.is_kill++; - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad user@host: %s@%s From: %s(via %s)", - parv[5], parv[6], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name); + rb_snprintf(squitreason, sizeof squitreason, + "Invalid UID %s for nick %s on %s/%s", + parv[8], parv[1], source_p->name, source_p->id); + exit_client(client_p, client_p, client_p, squitreason); return 0; } - if(!clean_uid(parv[8])) + if(!clean_username(parv[5]) || !clean_host(parv[6])) { ServerStats.is_kill++; sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad UID: %s From: %s(via %s)", - parv[8], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name); + "Bad user@host: %s@%s From: %s(via %s)", + parv[5], parv[6], source_p->name, client_p->name); + sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name); return 0; } @@ -450,7 +371,7 @@ ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *p { char *s = LOCAL_COPY(parv[9]); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s", - parv[0], parv[1]); + source_p->name, parv[1]); s[REALLEN] = '\0'; parv[9] = s; } @@ -492,6 +413,7 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * { struct Client *target_p; time_t newts = 0; + char squitreason[120]; newts = atol(parv[3]); @@ -502,7 +424,10 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * "with %d arguments (expecting 12)", client_p->name, parc); ilog(L_SERVER, "Excess parameters (%d) for command 'EUID' from %s.", parc, client_p->name); - exit_client(client_p, client_p, client_p, "Excess parameters to EUID command"); + rb_snprintf(squitreason, sizeof squitreason, + "Excess parameters (%d) to %s command, expecting %d", + parc, "EUID", 12); + exit_client(client_p, client_p, client_p, squitreason); return 0; } @@ -513,23 +438,22 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * return 0; } - if(!clean_username(parv[5]) || !clean_host(parv[6])) + if(!clean_uid(parv[8], source_p->id)) { - ServerStats.is_kill++; - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad user@host: %s@%s From: %s(via %s)", - parv[5], parv[6], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name); + rb_snprintf(squitreason, sizeof squitreason, + "Invalid UID %s for nick %s on %s/%s", + parv[8], parv[1], source_p->name, source_p->id); + exit_client(client_p, client_p, client_p, squitreason); return 0; } - if(!clean_uid(parv[8])) + if(!clean_username(parv[5]) || !clean_host(parv[6])) { ServerStats.is_kill++; sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad UID: %s From: %s(via %s)", - parv[8], source_p->name, client_p->name); - sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name); + "Bad user@host: %s@%s From: %s(via %s)", + parv[5], parv[6], source_p->name, client_p->name); + sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name); return 0; } @@ -548,7 +472,7 @@ ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char * { char *s = LOCAL_COPY(parv[11]); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s", - parv[0], parv[1]); + source_p->name, parv[1]); s[REALLEN] = '\0'; parv[11] = s; } @@ -605,7 +529,7 @@ ms_save(struct Client *client_p, struct Client *source_p, int parc, const char * * * input - nickname to check * output - 0 if erroneous, else 1 - * side effects - + * side effects - */ static int clean_nick(const char *nick, int loc_client) @@ -627,7 +551,7 @@ clean_nick(const char *nick, int loc_client) } /* nicklen is +1 */ - if(len >= NICKLEN) + if(len >= NICKLEN && len >= ConfigFileEntry.nicklen) return 0; return 1; @@ -684,10 +608,13 @@ clean_host(const char *host) } static int -clean_uid(const char *uid) +clean_uid(const char *uid, const char *sid) { int len = 1; + if(strncmp(uid, sid, strlen(sid))) + return 0; + if(!IsDigit(*uid++)) return 0; @@ -789,7 +716,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p, source_p->name, nick, source_p->username, source_p->host); /* send the nick change to the users channels */ - sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(source_p, NOCAPS, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); /* send the nick change to servers.. */ @@ -813,7 +740,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p, monitor_signon(source_p); /* Make sure everyone that has this client on its accept list - * loses that reference. + * loses that reference. */ /* we used to call del_all_accepts() here, but theres no real reason * to clear a clients own list of accepted clients. So just remove @@ -850,7 +777,7 @@ change_remote_nick(struct Client *client_p, struct Client *source_p, monitor_signoff(source_p); } - sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(source_p, NOCAPS, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); if(source_p->user) @@ -897,7 +824,7 @@ perform_nick_collides(struct Client *source_p, struct Client *client_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_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick collision on %s(%s <- %s)(both %s)", target_p->name, target_p->from->name, client_p->name, action); @@ -960,12 +887,12 @@ perform_nick_collides(struct Client *source_p, struct Client *client_p, else { if(sameuser) - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick collision on %s(%s <- %s)(older %s)", target_p->name, target_p->from->name, client_p->name, action); else - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick collision on %s(%s <- %s)(newer %s)", target_p->name, target_p->from->name, client_p->name, action); @@ -989,7 +916,7 @@ perform_nick_collides(struct Client *source_p, struct Client *client_p, (void) exit_client(client_p, target_p, &me, "Nick collision"); } - register_client(client_p, parc >= 10 ? source_p : NULL, + register_client(client_p, source_p, nick, newts, parc, parv); return 0; @@ -1014,7 +941,7 @@ perform_nickchange_collides(struct Client *source_p, struct Client *client_p, /* its a client changing nick and causing a collide */ if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user) { - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(both %s)", source_p->name, target_p->name, target_p->from->name, client_p->name, action); @@ -1057,12 +984,12 @@ perform_nickchange_collides(struct Client *source_p, struct Client *client_p, (!sameuser && newts > target_p->tsinfo)) { if(sameuser) - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(older %s)", source_p->name, target_p->name, target_p->from->name, client_p->name, action); else - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick change collision from %s to %s(%s <- %s)(newer %s)", source_p->name, target_p->name, target_p->from->name, client_p->name, action); @@ -1083,8 +1010,8 @@ perform_nickchange_collides(struct Client *source_p, struct Client *client_p, { ServerStats.is_kill++; - sendto_one_numeric(target_p, ERR_NICKCOLLISION, - form_str(ERR_NICKCOLLISION), target_p->name); + sendto_one_numeric(source_p, ERR_NICKCOLLISION, + form_str(ERR_NICKCOLLISION), source_p->name); /* kill the client issuing the nickchange */ kill_client_serv_butone(client_p, source_p, @@ -1102,12 +1029,12 @@ perform_nickchange_collides(struct Client *source_p, struct Client *client_p, else { if(sameuser) - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick collision on %s(%s <- %s)(older %s)", target_p->name, target_p->from->name, client_p->name, action); else - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_SKILL, L_ALL, "Nick collision on %s(%s <- %s)(newer %s)", target_p->name, target_p->from->name, client_p->name, action); @@ -1148,19 +1075,6 @@ register_client(struct Client *client_p, struct Client *server, const char *m; int flag; - if(server == NULL) - { - if((server = find_server(NULL, parv[7])) == NULL) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Ghost killed: %s on invalid server %s", - nick, parv[7]); - sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist)", - get_id(&me, client_p), nick, me.name); - return 0; - } - } - source_p = make_client(client_p); user = make_user(source_p); rb_dlinkAddTail(source_p, &source_p->node, &global_client_list); @@ -1197,7 +1111,7 @@ register_client(struct Client *client_p, struct Client *server, } else { - rb_strlcpy(source_p->info, parv[8], sizeof(source_p->info)); + s_assert(0); } /* remove any nd entries for this nick */ @@ -1258,23 +1172,6 @@ register_client(struct Client *client_p, struct Client *server, rb_dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users); - /* fake direction */ - if(source_p->servptr->from != source_p->from) - { - struct Client *target_p = source_p->servptr->from; - - sendto_realops_snomask(SNO_DEBUG, L_ALL, - "Bad User [%s] :%s USER %s@%s %s, != %s[%s]", - client_p->name, source_p->name, - source_p->username, source_p->host, - server->name, target_p->name, target_p->from->name); - kill_client(client_p, source_p, - "%s (NICK from wrong direction (%s != %s))", - me.name, server->name, target_p->from->name); - source_p->flags |= FLAGS_KILLED; - return exit_client(source_p, source_p, &me, "USER server wrong direction"); - } - call_hook(h_new_remote_user, source_p); return (introduce_client(client_p, source_p, user, nick, parc == 12)); @@ -1348,6 +1245,8 @@ static void bad_nickname(struct Client *client_p, const char *nick) sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :Squitting %s because of bad nickname %s (NICKLEN mismatch?)", me.id, client_p->name, nick); + ilog(L_SERVER, "Link %s cancelled, bad nickname %s sent (NICKLEN mismatch?)", + client_p->name, nick); rb_snprintf(squitreason, sizeof squitreason, "Bad nickname introduced [%s]", nick);