X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/a4721f5e9fd9dedc68534e736075a755645621f2..3321eef45a3a76f9c026bae5ae3f5dfbf4edf7fd:/ircd/s_user.c diff --git a/ircd/s_user.c b/ircd/s_user.c index 55a0bb55..cb4cf9db 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -20,8 +20,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA - * - * $Id: s_user.c 3586 2007-11-20 11:16:43Z nenolod $ */ #include "stdinc.h" @@ -29,7 +27,6 @@ #include "channel.h" #include "class.h" #include "client.h" -#include "common.h" #include "hash.h" #include "match.h" #include "ircd.h" @@ -51,7 +48,6 @@ #include "hook.h" #include "monitor.h" #include "snomask.h" -#include "blacklist.h" #include "substitution.h" #include "chmode.h" #include "s_assert.h" @@ -85,7 +81,7 @@ int user_modes[256] = { 0, /* O */ 0, /* P */ UMODE_NOFORWARD, /* Q */ - UMODE_REGONLYMSG, /* R */ + 0, /* R */ UMODE_SERVICE, /* S */ 0, /* T */ 0, /* U */ @@ -140,7 +136,7 @@ int user_modes[256] = { * output - * side effects - display to client user counts etc. */ -int +void show_lusers(struct Client *source_p) { if(rb_dlink_list_length(&lclient_list) > (unsigned long)MaxClientCount) @@ -190,8 +186,139 @@ show_lusers(struct Client *source_p) form_str(RPL_STATSCONN), MaxConnectionCount, MaxClientCount, Count.totalrestartcount); +} - return 0; +/* check if we should exit a client due to authd decision + * inputs - client server, client connecting + * outputs - true if exited, false if not + * side effects - messages/exits client if authd rejected and not exempt + */ +static bool +authd_check(struct Client *client_p, struct Client *source_p) +{ + struct ConfItem *aconf = source_p->localClient->att_conf; + rb_dlink_list varlist = { NULL, NULL, 0 }; + bool reject = false; + char *reason; + + if(source_p->preClient->auth.accepted == true) + return reject; + + substitution_append_var(&varlist, "nick", source_p->name); + substitution_append_var(&varlist, "ip", source_p->sockhost); + substitution_append_var(&varlist, "host", source_p->host); + substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->auth.data); + substitution_append_var(&varlist, "network-name", ServerInfo.network_name); + reason = substitution_parse(source_p->preClient->auth.reason, &varlist); + + switch(source_p->preClient->auth.cause) + { + case 'B': /* DNSBL */ + { + struct DNSBLEntryStats *stats; + char *dnsbl_name = source_p->preClient->auth.data; + + if(dnsbl_stats != NULL) + if((stats = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL) + stats->hits++; + + if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) + { + sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt", + source_p->sockhost, dnsbl_name); + break; + } + + sendto_realops_snomask(SNO_REJ, L_NETWIDE, + "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]", + dnsbl_name, source_p->name, source_p->username, source_p->host, + IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, + source_p->info); + + sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), + me.name, source_p->name, reason); + + sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s", + source_p->sockhost, dnsbl_name); + add_reject(source_p, NULL, NULL, NULL, "Banned (listed in a DNSBL)"); + exit_client(client_p, source_p, &me, "Banned (listed in a DNSBL)"); + reject = true; + } + break; + case 'O': /* OPM */ + { + char *proxy = source_p->preClient->auth.data; + char *port = strrchr(proxy, ':'); + + if(port == NULL) + { + /* This shouldn't happen, better tell the ops... */ + ierror("authd sent us a malformed OPM string %s", proxy); + sendto_realops_snomask(SNO_GENERAL, L_ALL, + "authd sent us a malformed OPM string %s", proxy); + break; + } + + /* Terminate the proxy type */ + *(port++) = '\0'; + + if(IsExemptKline(source_p) || IsConfExemptProxy(aconf)) + { + sendto_one_notice(source_p, + ":*** Your IP address %s has been detected as an open proxy (type %s, port %s), but you are exempt", + source_p->sockhost, proxy, port); + break; + } + sendto_realops_snomask(SNO_REJ, L_NETWIDE, + "Open proxy %s/%s: %s (%s@%s) [%s] [%s]", + proxy, port, + source_p->name, + source_p->username, source_p->host, + IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, + source_p->info); + + sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), + me.name, source_p->name, reason); + + sendto_one_notice(source_p, + ":*** Your IP address %s has been detected as an open proxy (type %s, port %s)", + source_p->sockhost, proxy, port); + add_reject(source_p, NULL, NULL, NULL, "Banned (Open proxy)"); + exit_client(client_p, source_p, &me, "Banned (Open proxy)"); + reject = true; + } + break; + default: /* Unknown, but handle the case properly */ + if(IsExemptKline(source_p)) + { + sendto_one_notice(source_p, + ":*** You were rejected, but you are exempt (reason: %s)", + reason); + break; + } + sendto_realops_snomask(SNO_REJ, L_NETWIDE, + "Rejected by authentication system (reason %s): %s (%s@%s) [%s] [%s]", + reason, source_p->name, source_p->username, source_p->host, + IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, + source_p->info); + + sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), + me.name, source_p->name, reason); + + sendto_one_notice(source_p, ":*** Rejected by authentication system: %s", + reason); + add_reject(source_p, NULL, NULL, NULL, "Banned (authentication system)"); + exit_client(client_p, source_p, &me, "Banned (authentication system)"); + reject = true; + break; + } + + if(reject) + ServerStats.is_ref++; + + substitution_free(&varlist); + + return reject; } /* @@ -216,14 +343,12 @@ show_lusers(struct Client *source_p) ** would just issue "KILL foobar" to clean out dups. But, ** this is not fair. It should actually request another ** nick from local user or kill him/her... -*/ - + */ int register_local_user(struct Client *client_p, struct Client *source_p) { struct ConfItem *aconf, *xconf; - struct User *user = source_p->user; - char tmpstr2[IRCD_BUFSIZE]; + char tmpstr2[BUFSIZE]; char ipaddr[HOSTIPLEN]; char myusername[USERLEN+1]; int status; @@ -241,9 +366,9 @@ register_local_user(struct Client *client_p, struct Client *source_p) { if(!(source_p->flags & FLAGS_PINGSENT) && source_p->localClient->random_ping == 0) { - source_p->localClient->random_ping = (unsigned long) (rand() * rand()) << 1; - sendto_one(source_p, "PING :%08lX", - (unsigned long) source_p->localClient->random_ping); + source_p->localClient->random_ping = (uint32_t)(((rand() * rand()) << 1) | 1); + sendto_one(source_p, "PING :%08X", + (unsigned int) source_p->localClient->random_ping); source_p->flags |= FLAGS_PINGSENT; return -1; } @@ -257,11 +382,13 @@ register_local_user(struct Client *client_p, struct Client *source_p) if(source_p->flags & FLAGS_CLICAP) return -1; - /* still has DNSbls to validate against */ - if(rb_dlink_list_length(&source_p->preClient->dnsbl_queries) > 0) + /* Waiting on authd */ + if(source_p->preClient->auth.cid) return -1; - client_p->localClient->last = rb_current_time(); + /* Set firsttime here so that post_registration_delay works from registration, + * rather than initial connection. */ + source_p->localClient->firsttime = client_p->localClient->last = rb_current_time(); /* XXX - fixme. we shouldnt have to build a users buffer twice.. */ if(!IsGotId(source_p) && (strchr(source_p->username, '[') != NULL)) @@ -289,13 +416,13 @@ register_local_user(struct Client *client_p, struct Client *source_p) /* Apply nick override */ if(*source_p->preClient->spoofnick) { - char note[NICKLEN + 10]; + char note[NAMELEN + 10]; del_from_client_hash(source_p->name, source_p); 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); + snprintf(note, sizeof(note), "Nick: %s", source_p->name); rb_note(source_p->localClient->F, note); } @@ -306,7 +433,6 @@ register_local_user(struct Client *client_p, struct Client *source_p) rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host)); } - aconf = source_p->localClient->att_conf; if(aconf == NULL) @@ -323,6 +449,14 @@ register_local_user(struct Client *client_p, struct Client *source_p) return (CLIENT_EXITED); } + if(IsSCTP(source_p) && !IsConfAllowSCTP(aconf)) + { + ServerStats.is_ref++; + sendto_one_notice(source_p, ":*** Notice -- You are not allowed to use SCTP on this server"); + exit_client(client_p, source_p, &me, "SCTP not allowed"); + return (CLIENT_EXITED); + } + if(!IsGotId(source_p)) { const char *p; @@ -355,7 +489,7 @@ register_local_user(struct Client *client_p, struct Client *source_p) } } - if(IsNeedSasl(aconf) && !*user->suser) + if(IsNeedSasl(aconf) && !*source_p->user->suser) { ServerStats.is_ref++; sendto_one_notice(source_p, ":*** Notice -- You need to identify via SASL to use this server"); @@ -393,7 +527,7 @@ register_local_user(struct Client *client_p, struct Client *source_p) } } - /* report if user has &^>= etc. and set flags as needed in source_p */ + /* report and set flags (kline exempt etc.) as needed in source_p */ report_and_set_user_flags(source_p, aconf); /* Limit clients */ @@ -421,51 +555,14 @@ register_local_user(struct Client *client_p, struct Client *source_p) (xconf = find_xline(source_p->info, 1)) != NULL) { ServerStats.is_ref++; - add_reject(source_p, xconf->host, NULL); + add_reject(source_p, xconf->host, NULL, NULL, NULL); exit_client(client_p, source_p, &me, "Bad user info"); return CLIENT_EXITED; } - /* dnsbl check */ - if (source_p->preClient->dnsbl_listed != NULL) - { - if (IsExemptKline(source_p) || IsConfExemptDNSBL(aconf)) - sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt", - source_p->sockhost, source_p->preClient->dnsbl_listed->host); - else - { - sendto_realops_snomask(SNO_REJ, L_NETWIDE, - "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]", - source_p->preClient->dnsbl_listed->host, - source_p->name, - source_p->username, source_p->host, - IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost, - source_p->info); - - rb_dlink_list varlist = { NULL, NULL, 0 }; - - substitution_append_var(&varlist, "nick", source_p->name); - substitution_append_var(&varlist, "ip", source_p->sockhost); - substitution_append_var(&varlist, "host", source_p->host); - substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->dnsbl_listed->host); - substitution_append_var(&varlist, "network-name", ServerInfo.network_name); - - ServerStats.is_ref++; - - sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP), - me.name, source_p->name, - substitution_parse(source_p->preClient->dnsbl_listed->reject_reason, &varlist)); - - substitution_free(&varlist); - - sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s", - source_p->sockhost, source_p->preClient->dnsbl_listed->host); - source_p->preClient->dnsbl_listed->hits++; - add_reject(source_p, NULL, NULL); - exit_client(client_p, source_p, &me, "*** Banned (DNS blacklist)"); - return CLIENT_EXITED; - } - } + /* authd rejection check */ + if(authd_check(client_p, source_p)) + return CLIENT_EXITED; /* valid user name check */ @@ -477,7 +574,7 @@ register_local_user(struct Client *client_p, struct Client *source_p) 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); + sprintf(tmpstr2, "Invalid username [%s]", source_p->username); exit_client(client_p, source_p, &me, tmpstr2); return (CLIENT_EXITED); } @@ -533,11 +630,11 @@ register_local_user(struct Client *client_p, struct Client *source_p) */ if(!*source_p->id) { - strcpy(source_p->id, generate_uid()); + rb_strlcpy(source_p->id, generate_uid(), sizeof(source_p->id)); add_to_id_hash(source_p->id, source_p); } - if (IsSSL(source_p)) + if (IsSSL(source_p) && !IsInsecure(source_p)) source_p->umodes |= UMODE_SSLCLIENT; if (source_p->umodes & UMODE_INVISIBLE) @@ -577,7 +674,8 @@ register_local_user(struct Client *client_p, struct Client *source_p) free_pre_client(source_p); - return (introduce_client(client_p, source_p, user, source_p->name, 1)); + introduce_client(client_p, source_p, source_p->user, source_p->name, 1); + return 0; } /* @@ -589,7 +687,7 @@ register_local_user(struct Client *client_p, struct Client *source_p) * of the net, either from a local client connect or * from a remote connect. */ -int +void introduce_client(struct Client *client_p, struct Client *source_p, struct User *user, const char *nick, int use_euid) { char ubuf[BUFSIZE]; @@ -700,21 +798,19 @@ introduce_client(struct Client *client_p, struct Client *source_p, struct User * hdata2.client = client_p; hdata2.target = source_p; call_hook(h_introduce_client, &hdata2); - - return 0; } /* * valid_hostname - check hostname for validity * * Inputs - pointer to user - * Output - YES if valid, NO if not + * Output - true if valid, false if not * Side effects - NONE * * NOTE: this doesn't allow a hostname to begin with a dot and * will not allow more dots than chars. */ -int +bool valid_hostname(const char *hostname) { const char *p = hostname, *last_slash = 0; @@ -723,18 +819,18 @@ valid_hostname(const char *hostname) s_assert(NULL != p); if(hostname == NULL) - return NO; + return false; if(!strcmp(hostname, "localhost")) - return YES; + return true; if('.' == *p || ':' == *p || '/' == *p) - return NO; + return false; while (*p) { if(!IsHostChar(*p)) - return NO; + return false; if(*p == '.' || *p == ':') found_sep++; else if(*p == '/') @@ -746,19 +842,19 @@ valid_hostname(const char *hostname) } if(found_sep == 0) - return NO; + return false; if(last_slash && IsDigit(last_slash[1])) - return NO; + return false; - return YES; + return true; } /* * valid_username - check username for validity * * Inputs - pointer to user - * Output - YES if valid, NO if not + * Output - true if valid, false if not * Side effects - NONE * * Absolutely always reject any '*' '!' '?' '@' in an user name @@ -766,7 +862,7 @@ valid_hostname(const char *hostname) * Allow '.' in username to allow for "first.last" * style of username */ -int +bool valid_username(const char *username) { int dots = 0; @@ -775,7 +871,7 @@ valid_username(const char *username) s_assert(NULL != p); if(username == NULL) - return NO; + return false; if('~' == *p) ++p; @@ -785,7 +881,7 @@ valid_username(const char *username) * or "-hi-@somehost", "h-----@somehost" would still be accepted. */ if(!IsAlNum(*p)) - return NO; + return false; while (*++p) { @@ -793,14 +889,14 @@ valid_username(const char *username) { dots++; if(dots > ConfigFileEntry.dots_in_ident) - return NO; + return false; if(!IsUserChar(p[1])) - return NO; + return false; } else if(!IsUserChar(*p)) - return NO; + return false; } - return YES; + return true; } /* report_and_set_user_flags @@ -831,7 +927,7 @@ report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf) 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 DNSBL listings"); /* If this user is exempt from user limits set it F lined" */ if(IsConfExemptLimits(aconf)) @@ -916,8 +1012,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char const char *pm; struct Client *target_p; int what, setflags; - int badflag = NO; /* Only send one bad flag notice */ - int showsnomask = NO; + bool badflag = false; /* Only send one bad flag notice */ + bool showsnomask = false; unsigned int setsnomask; char buf[BUFSIZE]; hook_data_umode_changed hdata; @@ -1023,16 +1119,23 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char if (!(source_p->umodes & UMODE_SERVNOTICE) && source_p->snomask != 0) { source_p->snomask = 0; - showsnomask = YES; + showsnomask = true; } - source_p->flags2 &= ~OPER_FLAGS; - - rb_free(source_p->localClient->opername); - source_p->localClient->opername = NULL; + source_p->flags &= ~OPER_FLAGS; rb_dlinkFindDestroy(source_p, &local_oper_list); - privilegeset_unref(source_p->localClient->privset); - source_p->localClient->privset = NULL; + } + + if(source_p->user->opername != NULL) + { + rb_free(source_p->user->opername); + source_p->user->opername = NULL; + } + + if(source_p->user->privset != NULL) + { + privilegeset_unref(source_p->user->privset); + source_p->user->privset = NULL; } rb_dlinkFindDestroy(source_p, &oper_list); @@ -1059,10 +1162,10 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char && (ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE)) { if (what == MODE_ADD || source_p->umodes & UMODE_SERVNOTICE) - badflag = YES; + badflag = true; continue; } - showsnomask = YES; + showsnomask = true; if(what == MODE_ADD) { if (parc > 3) @@ -1082,7 +1185,7 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char default: if (MyConnect(source_p) && *pm == 'Q' && !ConfigChannel.use_forward) { - badflag = YES; + badflag = true; break; } @@ -1094,7 +1197,7 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char || (orphaned_umodes & flag))) { if (what == MODE_ADD || source_p->umodes & flag) - badflag = YES; + badflag = true; } else { @@ -1107,7 +1210,7 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char else { if(MyConnect(source_p)) - badflag = YES; + badflag = true; } break; } @@ -1284,7 +1387,7 @@ user_welcome(struct Client *source_p) * output - none * side effects - opers up source_p using aconf for reference */ -int +void oper_up(struct Client *source_p, struct oper_conf *oper_p) { unsigned int old = source_p->umodes, oldsnomask = source_p->snomask; @@ -1318,9 +1421,9 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) SetExtendChans(source_p); SetExemptKline(source_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); + source_p->flags |= oper_p->flags; + source_p->user->opername = rb_strdup(oper_p->name); + source_p->user->privset = privilegeset_ref(oper_p->privset); rb_dlinkAddAlloc(source_p, &local_oper_list); rb_dlinkAddAlloc(source_p, &oper_list); @@ -1339,6 +1442,8 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s (%s!%s@%s) is now an operator", oper_p->name, source_p->name, source_p->username, source_p->host); + sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s OPER %s %s", + use_id(source_p), oper_p->name, oper_p->privset->name); if(!(old & UMODE_INVISIBLE) && IsInvisible(source_p)) ++Count.invisi; if((old & UMODE_INVISIBLE) && !IsInvisible(source_p)) @@ -1350,8 +1455,6 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p) 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); } /* @@ -1471,10 +1574,8 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use target_p->info); if(*mode) - sendto_channel_local_butone(target_p, ALL_MEMBERS, chptr, - ":%s MODE %s +%s %s", - target_p->servptr->name, - chptr->chname, mode, modeval); + sendto_channel_local_with_capability_butone(target_p, ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, chptr, + ":%s MODE %s +%s %s", target_p->servptr->name, chptr->chname, mode, modeval); *modeval = '\0'; } @@ -1513,7 +1614,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use rb_strlcpy(target_p->host, host, sizeof target_p->host); if (changed) - add_history(target_p, 1); + whowas_add_history(target_p, 1); del_from_client_hash(target_p->name, target_p); rb_strlcpy(target_p->name, nick, NICKLEN);