X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/0f021a8c1d618a1ca0997bb1b76bf255ba0a653f..77910830e39250078ffcd590969a8c9fb043db06:/src/s_user.c diff --git a/src/s_user.c b/src/s_user.c index 2428c856..12008848 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -31,15 +31,14 @@ #include "client.h" #include "common.h" #include "hash.h" -#include "irc_string.h" -#include "sprintf_irc.h" +#include "match.h" #include "ircd.h" #include "listener.h" #include "msg.h" #include "numeric.h" #include "s_conf.h" #include "s_newconf.h" -#include "s_log.h" +#include "logger.h" #include "s_serv.h" #include "s_stats.h" #include "scache.h" @@ -54,12 +53,12 @@ #include "snomask.h" #include "blacklist.h" #include "substitution.h" +#include "chmode.h" +#include "s_assert.h" static void report_and_set_user_flags(struct Client *, struct ConfItem *); void user_welcome(struct Client *source_p); -extern char *crypt(); - char umodebuf[128]; static int orphaned_umodes = 0; @@ -94,7 +93,7 @@ int user_modes[256] = { 0, /* W */ 0, /* X */ 0, /* Y */ - 0, /* Z */ + UMODE_SSLCLIENT, /* Z */ /* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */ UMODE_ADMIN, /* a */ 0, /* b */ @@ -154,16 +153,18 @@ show_lusers(struct Client *source_p) sendto_one_numeric(source_p, RPL_LUSERCLIENT, form_str(RPL_LUSERCLIENT), (Count.total - Count.invisi), - Count.invisi, rb_dlink_list_length(&global_serv_list)); + Count.invisi, + (int)rb_dlink_list_length(&global_serv_list)); if(rb_dlink_list_length(&oper_list) > 0) sendto_one_numeric(source_p, RPL_LUSEROP, - form_str(RPL_LUSEROP), rb_dlink_list_length(&oper_list)); + form_str(RPL_LUSEROP), + (int)rb_dlink_list_length(&oper_list)); if(rb_dlink_list_length(&unknown_list) > 0) sendto_one_numeric(source_p, RPL_LUSERUNKNOWN, form_str(RPL_LUSERUNKNOWN), - rb_dlink_list_length(&unknown_list)); + (int)rb_dlink_list_length(&unknown_list)); if(rb_dlink_list_length(&global_channel_list) > 0) sendto_one_numeric(source_p, RPL_LUSERCHANNELS, @@ -171,14 +172,14 @@ show_lusers(struct Client *source_p) rb_dlink_list_length(&global_channel_list)); sendto_one_numeric(source_p, RPL_LUSERME, form_str(RPL_LUSERME), - rb_dlink_list_length(&lclient_list), - rb_dlink_list_length(&serv_list)); + (int)rb_dlink_list_length(&lclient_list), + (int)rb_dlink_list_length(&serv_list)); sendto_one_numeric(source_p, RPL_LOCALUSERS, form_str(RPL_LOCALUSERS), - rb_dlink_list_length(&lclient_list), + (int)rb_dlink_list_length(&lclient_list), Count.max_loc, - rb_dlink_list_length(&lclient_list), + (int)rb_dlink_list_length(&lclient_list), Count.max_loc); sendto_one_numeric(source_p, RPL_GLOBALUSERS, form_str(RPL_GLOBALUSERS), @@ -262,8 +263,6 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char return -1; client_p->localClient->last = rb_current_time(); - /* Straight up the maximum rate of flooding... */ - source_p->localClient->allow_read = MAX_FLOOD_BURST; /* XXX - fixme. we shouldnt have to build a users buffer twice.. */ if(!IsGotId(source_p) && (strchr(username, '[') != NULL)) @@ -293,7 +292,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char char note[NICKLEN + 10]; del_from_client_hash(source_p->name, source_p); - strlcpy(source_p->name, source_p->preClient->spoofnick, NICKLEN + 1); + rb_strlcpy(source_p->name, source_p->preClient->spoofnick, NICKLEN + 1); add_to_client_hash(source_p->name, source_p); rb_snprintf(note, NICKLEN + 10, "Nick: %s", source_p->name); @@ -304,7 +303,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char { sendto_one_notice(source_p, ":*** Notice -- You have an illegal character in your hostname"); - strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); + rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); } @@ -316,6 +315,14 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char return (CLIENT_EXITED); } + if(IsConfSSLNeeded(aconf) && !IsSSL(source_p)) + { + ServerStats.is_ref++; + sendto_one_notice(source_p, ":*** Notice -- You need to use SSL/TLS to use this server"); + exit_client(client_p, source_p, &me, "Use SSL/TLS"); + return (CLIENT_EXITED); + } + if(!IsGotId(source_p)) { const char *p; @@ -323,14 +330,14 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char if(IsNeedIdentd(aconf)) { - ServerStats->is_ref++; + ServerStats.is_ref++; sendto_one_notice(source_p, ":*** Notice -- You need to install identd to use this server"); exit_client(client_p, source_p, &me, "Install identd"); return (CLIENT_EXITED); } /* dont replace username if its supposed to be spoofed --fl */ - if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->name, '@')) + if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->info.name, '@')) { p = username; @@ -350,7 +357,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char if(IsNeedSasl(aconf) && !*user->suser) { - ServerStats->is_ref++; + ServerStats.is_ref++; sendto_one_notice(source_p, ":*** Notice -- You need to identify via SASL to use this server"); exit_client(client_p, source_p, &me, "SASL access only"); return (CLIENT_EXITED); @@ -364,13 +371,13 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char if(EmptyString(source_p->localClient->passwd)) encr = ""; else if(IsConfEncrypted(aconf)) - encr = crypt(source_p->localClient->passwd, aconf->passwd); + encr = rb_crypt(source_p->localClient->passwd, aconf->passwd); else encr = source_p->localClient->passwd; - if(strcmp(encr, aconf->passwd)) + if(encr == NULL || strcmp(encr, aconf->passwd)) { - ServerStats->is_ref++; + ServerStats.is_ref++; sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name); exit_client(client_p, source_p, &me, "Bad Password"); return (CLIENT_EXITED); @@ -404,7 +411,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char sendto_realops_snomask(SNO_FULL, L_ALL, "Too many clients, rejecting %s[%s].", source_p->name, source_p->host); - ServerStats->is_ref++; + ServerStats.is_ref++; exit_client(client_p, source_p, &me, "Sorry, server is full - try later"); return (CLIENT_EXITED); } @@ -413,8 +420,8 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char if(!IsExemptKline(source_p) && (xconf = find_xline(source_p->info, 1)) != NULL) { - ServerStats->is_ref++; - add_reject(source_p, xconf->name, NULL); + ServerStats.is_ref++; + add_reject(source_p, xconf->host, NULL); exit_client(client_p, source_p, &me, "Bad user info"); return CLIENT_EXITED; } @@ -435,7 +442,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->dnsbl_listed->host); substitution_append_var(&varlist, "network-name", ServerInfo.network_name); - ServerStats->is_ref++; + ServerStats.is_ref++; sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), me.name, source_p->name, @@ -459,7 +466,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char sendto_realops_snomask(SNO_REJ, L_ALL, "Invalid username: %s (%s@%s)", source_p->name, source_p->username, source_p->host); - ServerStats->is_ref++; + ServerStats.is_ref++; sendto_one_notice(source_p, ":*** Your username is invalid. Please make sure that your username contains " "only alphanumeric characters."); rb_sprintf(tmpstr2, "Invalid username [%s]", source_p->username); @@ -470,14 +477,14 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char /* end of valid user name check */ /* Store original hostname -- jilles */ - strlcpy(source_p->orighost, source_p->host, HOSTLEN + 1); + rb_strlcpy(source_p->orighost, source_p->host, HOSTLEN + 1); /* Spoof user@host */ if(*source_p->preClient->spoofuser) - strlcpy(source_p->username, source_p->preClient->spoofuser, USERLEN + 1); + rb_strlcpy(source_p->username, source_p->preClient->spoofuser, USERLEN + 1); if(*source_p->preClient->spoofhost) { - strlcpy(source_p->host, source_p->preClient->spoofhost, HOSTLEN + 1); + rb_strlcpy(source_p->host, source_p->preClient->spoofhost, HOSTLEN + 1); if (irccmp(source_p->host, source_p->orighost)) SetDynSpoof(source_p); } @@ -494,7 +501,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char /* To avoid inconsistencies, do not abort the registration * starting from this point -- jilles */ - inetntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr)); + rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr)); sendto_realops_snomask(SNO_CCONN, L_ALL, "Client connecting: %s (%s@%s) [%s] {%s} [%s]", @@ -522,11 +529,13 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char add_to_id_hash(source_p->id, source_p); } + if (IsSSL(source_p)) + source_p->umodes |= UMODE_SSLCLIENT; + if (source_p->umodes & UMODE_INVISIBLE) Count.invisi++; s_assert(!IsClient(source_p)); - del_unknown_ip(source_p); rb_dlinkMoveNode(&source_p->localClient->tnode, &unknown_list, &lclient_list); SetClient(source_p); @@ -537,8 +546,6 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char if(++Count.total > Count.max_tot) Count.max_tot = Count.total; - source_p->localClient->allow_read = MAX_FLOOD_BURST; - Count.totalrestartcount++; s_assert(source_p->localClient != NULL); @@ -553,7 +560,9 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char /* they get a reduced limit */ if(find_tgchange(source_p->sockhost)) - USED_TARGETS(source_p) = 6; + source_p->localClient->targets_free = TGCHANGE_INITIAL_LOW; + else + source_p->localClient->targets_free = TGCHANGE_INITIAL; monitor_signon(source_p); user_welcome(source_p); @@ -580,6 +589,7 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * char *p; hook_data_umode_changed hdata; hook_data_client hdata2; + char sockhost[HOSTLEN]; if(MyClient(source_p)) send_umode(source_p, source_p, 0, 0, ubuf); @@ -592,76 +602,59 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * ubuf[1] = '\0'; } - /* if it has an ID, introduce it with its id to TS6 servers, - * otherwise introduce it normally to all. - */ - if(has_id(source_p)) + s_assert(has_id(source_p)); + + if(source_p->sockhost[0] == ':') { - char sockhost[HOSTLEN]; - if(source_p->sockhost[0] == ':') - { - sockhost[0] = '0'; - sockhost[1] = '\0'; - strlcat(sockhost, source_p->sockhost, sizeof(sockhost)); - } else - strcpy(sockhost, source_p->sockhost); + sockhost[0] = '0'; + sockhost[1] = '\0'; + rb_strlcat(sockhost, source_p->sockhost, sizeof(sockhost)); + } else + strcpy(sockhost, source_p->sockhost); - if (use_euid) - sendto_server(client_p, NULL, CAP_EUID | CAP_TS6, NOCAPS, - ":%s EUID %s %d %ld %s %s %s %s %s %s %s :%s", - source_p->servptr->id, nick, - source_p->hopcount + 1, - (long) source_p->tsinfo, ubuf, - source_p->username, source_p->host, - IsIPSpoof(source_p) ? "0" : sockhost, - source_p->id, - IsDynSpoof(source_p) ? source_p->orighost : "*", - EmptyString(source_p->user->suser) ? "*" : source_p->user->suser, - source_p->info); - - sendto_server(client_p, NULL, CAP_TS6, use_euid ? CAP_EUID : NOCAPS, - ":%s UID %s %d %ld %s %s %s %s %s :%s", - source_p->servptr->id, nick, - source_p->hopcount + 1, - (long) source_p->tsinfo, ubuf, - source_p->username, source_p->host, - IsIPSpoof(source_p) ? "0" : sockhost, - source_p->id, source_p->info); - - sendto_server(client_p, NULL, NOCAPS, CAP_TS6, - "NICK %s %d %ld %s %s %s %s :%s", - nick, source_p->hopcount + 1, - (long) source_p->tsinfo, - ubuf, source_p->username, source_p->host, - source_p->servptr->name, source_p->info); - } - else - sendto_server(client_p, NULL, NOCAPS, NOCAPS, - "NICK %s %d %ld %s %s %s %s :%s", - nick, source_p->hopcount + 1, - (long) source_p->tsinfo, - ubuf, source_p->username, source_p->host, - source_p->servptr->name, source_p->info); + if (use_euid) + sendto_server(client_p, NULL, CAP_EUID | CAP_TS6, NOCAPS, + ":%s EUID %s %d %ld %s %s %s %s %s %s %s :%s", + source_p->servptr->id, nick, + source_p->hopcount + 1, + (long) source_p->tsinfo, ubuf, + source_p->username, source_p->host, + IsIPSpoof(source_p) ? "0" : sockhost, + source_p->id, + IsDynSpoof(source_p) ? source_p->orighost : "*", + EmptyString(source_p->user->suser) ? "*" : source_p->user->suser, + source_p->info); + + sendto_server(client_p, NULL, CAP_TS6, use_euid ? CAP_EUID : NOCAPS, + ":%s UID %s %d %ld %s %s %s %s %s :%s", + source_p->servptr->id, nick, + source_p->hopcount + 1, + (long) source_p->tsinfo, ubuf, + source_p->username, source_p->host, + IsIPSpoof(source_p) ? "0" : sockhost, + source_p->id, source_p->info); + + if(!EmptyString(source_p->certfp)) + sendto_server(client_p, NULL, CAP_TS6, NOCAPS, + ":%s ENCAP * CERTFP :%s", + use_id(source_p), source_p->certfp); if (IsDynSpoof(source_p)) { sendto_server(client_p, NULL, CAP_TS6, use_euid ? CAP_EUID : NOCAPS, ":%s ENCAP * REALHOST %s", use_id(source_p), source_p->orighost); - sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s ENCAP * REALHOST %s", - source_p->name, source_p->orighost); } + if (!EmptyString(source_p->user->suser)) { sendto_server(client_p, NULL, CAP_TS6, use_euid ? CAP_EUID : NOCAPS, ":%s ENCAP * LOGIN %s", use_id(source_p), source_p->user->suser); - sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s ENCAP * LOGIN %s", - source_p->name, source_p->user->suser); } if(MyConnect(source_p) && source_p->localClient->passwd) { - if (ConfigFileEntry.identifyservice[0] != '\0' && - ConfigFileEntry.identifycommand[0] != '\0') + if (!EmptyString(ConfigFileEntry.identifyservice) && + !EmptyString(ConfigFileEntry.identifycommand)) { /* use user@server */ p = strchr(ConfigFileEntry.identifyservice, '@'); @@ -670,11 +663,21 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * else identifyservice_p = NULL; if (identifyservice_p != NULL) - sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s", - get_id(source_p, identifyservice_p), - ConfigFileEntry.identifyservice, - ConfigFileEntry.identifycommand, - source_p->localClient->passwd); + { + if (!EmptyString(source_p->localClient->auth_user)) + sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s %s", + get_id(source_p, identifyservice_p), + ConfigFileEntry.identifyservice, + ConfigFileEntry.identifycommand, + source_p->localClient->auth_user, + source_p->localClient->passwd); + else + sendto_one(identifyservice_p, ":%s PRIVMSG %s :%s %s", + get_id(source_p, identifyservice_p), + ConfigFileEntry.identifyservice, + ConfigFileEntry.identifycommand, + source_p->localClient->passwd); + } } memset(source_p->localClient->passwd, 0, strlen(source_p->localClient->passwd)); rb_free(source_p->localClient->passwd); @@ -715,7 +718,7 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * int valid_hostname(const char *hostname) { - const char *p = hostname; + const char *p = hostname, *last_slash = 0; int found_sep = 0; s_assert(NULL != p); @@ -723,7 +726,7 @@ valid_hostname(const char *hostname) if(hostname == NULL) return NO; - if('.' == *p || ':' == *p) + if('.' == *p || ':' == *p || '/' == *p) return NO; while (*p) @@ -732,13 +735,21 @@ valid_hostname(const char *hostname) return NO; if(*p == '.' || *p == ':') found_sep++; + else if(*p == '/') + { + found_sep++; + last_slash = p; + } p++; } if(found_sep == 0) - return(NO); + return NO; - return (YES); + if(last_slash && IsDigit(last_slash[1])) + return NO; + + return YES; } /* @@ -805,72 +816,86 @@ report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf) /* If this user is being spoofed, tell them so */ if(IsConfDoSpoofIp(aconf)) { - sendto_one_notice(source_p, ":*** Spoofing your IP. congrats."); + sendto_one_notice(source_p, ":*** Spoofing your IP"); } /* If this user is in the exception class, Set it "E lined" */ if(IsConfExemptKline(aconf)) { SetExemptKline(source_p); - sendto_one_notice(source_p, ":*** You are exempt from K/G/X lines. congrats."); - } - - if(IsConfExemptGline(aconf)) - { - SetExemptGline(source_p); - - /* dont send both a kline and gline exempt notice */ - if(!IsConfExemptKline(aconf)) - sendto_one_notice(source_p, ":*** You are exempt from G lines."); + sendto_one_notice(source_p, ":*** You are exempt from K/X lines"); } if(IsConfExemptDNSBL(aconf)) /* kline exempt implies this, don't send both */ if(!IsConfExemptKline(aconf)) - sendto_one_notice(source_p, ":*** You are exempt from DNS blacklists."); + sendto_one_notice(source_p, ":*** You are exempt from DNS blacklists"); /* If this user is exempt from user limits set it F lined" */ if(IsConfExemptLimits(aconf)) { - sendto_one_notice(source_p, ":*** You are exempt from user limits. congrats."); + sendto_one_notice(source_p, ":*** You are exempt from user limits"); } if(IsConfExemptFlood(aconf)) { SetExemptFlood(source_p); - sendto_one_notice(source_p, ":*** You are exempt from flood limits."); + sendto_one_notice(source_p, ":*** You are exempt from flood limits"); } if(IsConfExemptSpambot(aconf)) { SetExemptSpambot(source_p); - sendto_one_notice(source_p, ":*** You are exempt from spambot checks."); + sendto_one_notice(source_p, ":*** You are exempt from spambot checks"); } if(IsConfExemptJupe(aconf)) { SetExemptJupe(source_p); - sendto_one_notice(source_p, ":*** You are exempt from juped channel warnings."); + sendto_one_notice(source_p, ":*** You are exempt from juped channel warnings"); } if(IsConfExemptResv(aconf)) { SetExemptResv(source_p); - sendto_one_notice(source_p, ":*** You are exempt from resvs."); + sendto_one_notice(source_p, ":*** You are exempt from resvs"); } if(IsConfExemptShide(aconf)) { SetExemptShide(source_p); - sendto_one_notice(source_p, ":*** You are exempt from serverhiding."); + sendto_one_notice(source_p, ":*** You are exempt from serverhiding"); } } +static void +show_other_user_mode(struct Client *source_p, struct Client *target_p) +{ + int i; + char buf[BUFSIZE]; + char *m; + + m = buf; + *m++ = '+'; + + for (i = 0; i < 128; i++) /* >= 127 is extended ascii */ + if (target_p->umodes & user_modes[i]) + *m++ = (char) i; + *m = '\0'; + + if (MyConnect(target_p) && target_p->snomask != 0) + sendto_one_notice(source_p, ":Modes for %s are %s %s", + target_p->name, buf, + construct_snobuf(target_p->snomask)); + else + sendto_one_notice(source_p, ":Modes for %s are %s", + target_p->name, buf); +} + /* * user_mode - set get current users mode * * m_umode() added 15/10/91 By Darren Reed. - * parv[0] - sender * parv[1] - username to change mode for * parv[2] - modes to change */ @@ -916,9 +941,12 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char return 0; } - if(source_p != target_p || target_p->from != source_p->from) + if(source_p != target_p) { - sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name); + if (MyOper(source_p) && parc < 3) + show_other_user_mode(source_p, target_p); + else + sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name); return 0; } @@ -995,6 +1023,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char source_p->localClient->opername = NULL; rb_dlinkFindDestroy(source_p, &local_oper_list); + privilegeset_unref(source_p->localClient->privset); + source_p->localClient->privset = NULL; } rb_dlinkFindDestroy(source_p, &oper_list); @@ -1007,6 +1037,7 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char /* can only be set on burst */ case 'S': + case 'Z': case ' ': case '\n': case '\r': @@ -1041,7 +1072,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char } /* FALLTHROUGH */ default: - if (MyConnect(source_p) && *pm == 'Q' && !ConfigChannel.use_forward) { + if (MyConnect(source_p) && *pm == 'Q' && !ConfigChannel.use_forward) + { badflag = YES; break; } @@ -1214,7 +1246,7 @@ user_welcome(struct Client *source_p) sendto_one_numeric(source_p, RPL_YOURHOST, form_str(RPL_YOURHOST), get_listener_name(source_p->localClient->listener), ircd_version); sendto_one_numeric(source_p, RPL_CREATED, form_str(RPL_CREATED), creation); - sendto_one_numeric(source_p, RPL_MYINFO, form_str(RPL_MYINFO), me.name, ircd_version, umodebuf); + sendto_one_numeric(source_p, RPL_MYINFO, form_str(RPL_MYINFO), me.name, ircd_version, umodebuf, cflagsmyinfo); show_isupport(source_p); @@ -1279,6 +1311,7 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) source_p->flags2 |= oper_p->flags; source_p->localClient->opername = rb_strdup(oper_p->name); + source_p->localClient->privset = privilegeset_ref(oper_p->privset); rb_dlinkAddAlloc(source_p, &local_oper_list); rb_dlinkAddAlloc(source_p, &oper_list); @@ -1295,7 +1328,7 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) call_hook(h_umode_changed, &hdata); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "%s (%s@%s) is now an operator", source_p->name, + "%s (%s!%s@%s) is now an operator", oper_p->name, source_p->name, source_p->username, source_p->host); if(!(old & UMODE_INVISIBLE) && IsInvisible(source_p)) ++Count.invisi; @@ -1305,7 +1338,8 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) sendto_one_numeric(source_p, RPL_SNOMASK, form_str(RPL_SNOMASK), construct_snobuf(source_p->snomask)); sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name); - sendto_one_notice(source_p, ":*** Oper privs are %s", get_oper_privs(oper_p->flags)); + sendto_one_notice(source_p, ":*** Oper privilege set is %s", oper_p->privset->name); + sendto_one_notice(source_p, ":*** Oper privs are %s", oper_p->privset->privs); send_oper_motd(source_p); return (1); @@ -1369,7 +1403,7 @@ construct_umodebuf(void) void change_nick_user_host(struct Client *target_p, const char *nick, const char *user, - const char *host, int newts, char *format, ...) + const char *host, int newts, const char *format, ...) { rb_dlink_node *ptr; struct Channel *chptr; @@ -1395,7 +1429,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use vsnprintf(reason, 255, format, ap); va_end(ap); - sendto_common_channels_local_butone(target_p, ":%s!%s@%s QUIT :%s", + sendto_common_channels_local_butone(target_p, NOCAPS, ":%s!%s@%s QUIT :%s", target_p->name, target_p->username, target_p->host, reason); @@ -1420,8 +1454,13 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use *mptr = '\0'; - sendto_channel_local_butone(target_p, ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", - nick, user, host, chptr->chname); + sendto_channel_local_with_capability_butone(target_p, ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN, chptr, + ":%s!%s@%s JOIN %s", nick, user, host, chptr->chname); + sendto_channel_local_with_capability_butone(target_p, ALL_MEMBERS, CLICAP_EXTENDED_JOIN, NOCAPS, chptr, + ":%s!%s@%s JOIN %s %s :%s", nick, user, host, chptr->chname, + EmptyString(target_p->user->suser) ? "*" : target_p->user->suser, + target_p->info); + if(*mode) sendto_channel_local_butone(target_p, ALL_MEMBERS, chptr, ":%s MODE %s +%s %s", @@ -1431,25 +1470,39 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use *modeval = '\0'; } + /* Resend away message to away-notify enabled clients. */ + if (target_p->user->away) + sendto_common_channels_local_butone(target_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s", + target_p->name, target_p->username, target_p->host, + target_p->user->away); + if(MyClient(target_p) && changed_case) sendto_one(target_p, ":%s!%s@%s NICK %s", target_p->name, target_p->username, target_p->host, nick); + + /* TODO: send some snotes to SNO_NCHANGE/SNO_CCONN/SNO_CCONNEXT? */ } else if(changed_case) { - sendto_common_channels_local(target_p, ":%s!%s@%s NICK :%s", + sendto_common_channels_local(target_p, NOCAPS, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->host, nick); + + if(MyConnect(target_p)) + sendto_realops_snomask(SNO_NCHANGE, L_ALL, + "Nick change: From %s to %s [%s@%s]", + target_p->name, nick, + target_p->username, target_p->host); } - strlcpy(target_p->username, user, sizeof target_p->username); - strlcpy(target_p->host, host, sizeof target_p->host); + rb_strlcpy(target_p->username, user, sizeof target_p->username); + rb_strlcpy(target_p->host, host, sizeof target_p->host); if (changed) add_history(target_p, 1); del_from_client_hash(target_p->name, target_p); - strlcpy(target_p->name, nick, NICKLEN); + rb_strlcpy(target_p->name, nick, NICKLEN); add_to_client_hash(target_p->name, target_p); if(changed)