/* check_clean_nick() * * input - pointer to source * - * - nickname * - truncated nickname * - origin of client * - pointer to server nick is coming from * 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, struct Client *server_p) { /* the old code did some wacky stuff here, if the nick is invalid, kill it * and dont bother messing at all */ if (!valid_nickname(nick, 0)) { ++ServerStats.is_kill; sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Bad/long Nick: %s From: %s(via %s)", nick, server_p->name, client_p->name); sendto_one(client_p, ":%s KILL %s :%s (Bad Nickname)", me.name, nick, me.name); /* bad nick change */ if (source_p != client_p) { kill_client_ll_serv_butone(client_p, source_p, "%s (Bad Nickname)", me.name); AddFlag(source_p, FLAGS_KILLED); exit_client(source_p, &me, "Bad Nickname"); } return 1; } return 0; }
/* check_clean_nick() * * input - pointer to source * - * - nickname * - truncated nickname * - origin of client * - pointer to server nick is coming from * output - none * side effects - if nickname is erroneous, or a different length to * truncated nickname, return 1 */ static int check_clean_nick(struct Client *source_p, char *nick, struct Client *server_p) { /* * The old code did some wacky stuff here, if the nick is invalid, kill it * and don't bother messing at all */ if (!valid_nickname(nick, 0)) { ++ServerStats.is_kill; sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Bad/long Nick: %s From: %s(via %s)", nick, server_p->name, source_p->from->name); sendto_one(source_p, ":%s KILL %s :%s (Bad Nickname)", me.name, nick, me.name); /* Bad nick change */ if (IsClient(source_p) && !MyConnect(source_p)) { sendto_server(source_p, 0, 0, ":%s KILL %s :%s (Bad Nickname)", me.id, source_p->id, me.name); AddFlag(source_p, FLAGS_KILLED); exit_client(source_p, "Bad Nickname"); } return 1; } return 0; }
/*! \brief NICK command handler (called by unregistered, * locally connected clients) * * \param client_p Pointer to allocated Client struct with physical connection * to this server, i.e. with an open socket connected. * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = sender prefix * - parv[1] = nickname */ static void mr_nick(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char nick[NICKLEN + 1] = { '\0' }; char *s = NULL; struct Client *target_p = NULL; struct MaskItem *conf = NULL; if (parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, source_p->name[0] ? source_p->name : "*"); return; } /* Terminate the nick at the first ~ */ if ((s = strchr(parv[1], '~')) != NULL) *s = '\0'; /* Copy the nick and terminate it */ strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1)); /* Check the nickname is ok */ if (!valid_nickname(nick, 1)) { sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name[0] ? source_p->name : "*", parv[1], "Erroneous Nickname"); return; } /* Check if the nick is resv'd */ if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0))) { ++conf->count; sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name[0] ? source_p->name : "*", nick, conf->reason); sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Forbidding reserved nick [%s] from user %s", nick, get_client_name(client_p, HIDE_IP)); return; } if ((target_p = hash_find_client(nick)) == NULL) set_initial_nick(source_p, nick); else if (source_p == target_p) strlcpy(source_p->name, nick, sizeof(source_p->name)); else sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick); }
/*! \brief NICK command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname */ static int mr_nick(struct Client *source_p, int parc, char *parv[]) { char nick[NICKLEN + 1] = ""; struct Client *target_p = NULL; struct MaskItem *conf = NULL; if (parc < 2 || EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN); return 0; } /* Copy the nick and terminate it */ strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1)); /* Check the nickname is ok */ if (!valid_nickname(nick, 1)) { sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, parv[1], "Erroneous Nickname"); return 0; } /* Check if the nick is resv'd */ if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0))) { ++conf->count; sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason); sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Forbidding reserved nick %s from user %s", nick, get_client_name(source_p, HIDE_IP)); return 0; } if ((target_p = hash_find_client(nick)) == NULL || target_p == source_p) set_initial_nick(source_p, nick); else sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name); return 0; }
/*! \brief NICK command handler (called by already registered, * locally connected clients) * * \param client_p Pointer to allocated Client struct with physical connection * to this server, i.e. with an open socket connected. * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = sender prefix * - parv[1] = nickname */ static void m_nick(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char nick[NICKLEN + 1] = { '\0' }; struct Client *target_p = NULL; struct MaskItem *conf = NULL; assert(source_p == client_p); if (parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, source_p->name); return; } /* mark end of grace period, to prevent nickflooding */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); /* terminate nick to NICKLEN */ strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1)); /* check the nickname is ok */ if (!valid_nickname(nick, 1)) { sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick, "Erroneous Nickname"); return; } if (!IsExemptResv(source_p) && !(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) && (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0))) { ++conf->count; sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick, conf->reason); sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Forbidding reserved nick [%s] from user %s", nick, get_client_name(client_p, HIDE_IP)); return; } if ((target_p = hash_find_client(nick)) == NULL) change_local_nick(source_p, nick); else if (target_p == source_p) { /* * If (target_p == source_p) the client is changing nicks between * equivalent nicknames ie: [nick] -> {nick} */ /* Check the nick isn't exactly the same */ if (strcmp(target_p->name, nick)) change_local_nick(source_p, nick); } else if (IsUnknown(target_p)) { /* * If the client that has the nick isn't registered yet (nick but no * user) then drop the unregged client */ exit_client(target_p, &me, "Overridden"); change_local_nick(source_p, nick); } else sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, source_p->name, nick); }
/*! \brief NICK command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname */ static int m_nick(struct Client *source_p, int parc, char *parv[]) { char nick[NICKLEN + 1] = ""; struct Client *target_p = NULL; struct MaskItem *conf = NULL; assert(MyClient(source_p)); if (parc < 2 || EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN); return 0; } /* Mark end of grace period, to prevent nickflooding */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); /* Terminate nick to NICKLEN */ strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1)); /* Check the nickname is ok */ if (!valid_nickname(nick, 1)) { sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname"); return 0; } if (!HasFlag(source_p, FLAGS_EXEMPTRESV) && !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) && (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0))) { ++conf->count; sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason); sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Forbidding reserved nick %s from user %s", nick, get_client_name(source_p, HIDE_IP)); return 0; } if ((target_p = hash_find_client(nick)) == NULL) change_local_nick(source_p, nick); else if (target_p == source_p) { /* * If (target_p == source_p) the client is changing nicks between * equivalent nicknames ie: [nick] -> {nick} */ /* Check the nick isn't exactly the same */ if (strcmp(target_p->name, nick)) change_local_nick(source_p, nick); } else if (IsUnknown(target_p)) { /* * If the client that has the nick isn't registered yet (nick but no * user) then drop the unregged client */ exit_client(target_p, "Overridden by other sign on"); change_local_nick(source_p, nick); } else sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name); return 0; }
/*! \brief SVSNICK command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = old nickname * - parv[2] = new nickname * - parv[3] = timestamp */ static int ms_svsnick(struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL, *exists_p = NULL; if (!HasFlag(source_p, FLAGS_SERVICE) || !valid_nickname(parv[2], 1)) return 0; if ((target_p = find_person(source_p, parv[1])) == NULL) return 0; if (!MyConnect(target_p)) { if (target_p->from == source_p->from) { sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Received wrong-direction SVSNICK " "for %s (behind %s) from %s", target_p->name, source_p->from->name, get_client_name(source_p, HIDE_IP)); return 0; } sendto_one(target_p, ":%s SVSNICK %s %s %s", source_p->id, target_p->id, parv[2], parv[3]); return 0; } if ((exists_p = hash_find_client(parv[2]))) { if (target_p == exists_p) { if (!strcmp(target_p->name, parv[2])) return 0; } else if (IsUnknown(exists_p)) exit_client(exists_p, "SVSNICK Override"); else { exit_client(target_p, "SVSNICK Collide"); return 0; } } target_p->tsinfo = strtoimax(parv[3], NULL, 10); clear_ban_cache_client(target_p); watch_check_hash(target_p, RPL_LOGOFF); if (HasUMode(target_p, UMODE_REGISTERED)) { const unsigned int oldmodes = target_p->umodes; char modebuf[IRCD_BUFSIZE] = ""; DelUMode(target_p, UMODE_REGISTERED); send_umode(target_p, target_p, oldmodes, modebuf); } sendto_common_channels_local(target_p, 1, 0, 0, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->host, parv[2]); whowas_add_history(target_p, 1); sendto_server(NULL, 0, 0, ":%s NICK %s :%ju", target_p->id, parv[2], target_p->tsinfo); hash_del_client(target_p); strlcpy(target_p->name, parv[2], sizeof(target_p->name)); hash_add_client(target_p); watch_check_hash(target_p, RPL_LOGON); fd_note(&target_p->connection->fd, "Nick: %s", target_p->name); return 0; }