diff --git a/doc/reference.conf b/doc/reference.conf index 592380af..98f20931 100644 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -395,6 +395,8 @@ auth { * need_ssl | require SSL/TLS for user in this class * need_sasl | require SASL id for user in this class * extend_chans | allow this user to join more channels than normal + * kline_spoof_ip | if this block has a spoof host, klines match only + * | the spoof and not the underlying IP */ flags = kline_exempt, exceed_limit; diff --git a/include/hostmask.h b/include/hostmask.h index bb41b6c2..28b47d66 100644 --- a/include/hostmask.h +++ b/include/hostmask.h @@ -49,8 +49,9 @@ struct ConfItem *find_address_conf(const char *host, const char *sockhost, struct ConfItem *find_dline(struct sockaddr *, int); -#define find_kline(x) (find_conf_by_address((x)->host, (x)->sockhost, \ - (x)->orighost, \ +#define find_kline(x) ((IsConfDoSpoofIp((x)->localClient->att_conf) && IsConfKlineSpoof((x)->localClient->att_conf)) ? \ + find_conf_by_address((x)->orighost, NULL, NULL, NULL, CONF_KILL, AF_INET, (x)->username, NULL) : \ + find_conf_by_address((x)->host, (x)->sockhost, (x)->orighost, \ (struct sockaddr *)&(x)->localClient->ip, CONF_KILL,\ GET_SS_FAMILY(&(x)->localClient->ip), (x)->username, NULL)) diff --git a/include/s_conf.h b/include/s_conf.h index e04dcee5..703f4eac 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -112,6 +112,7 @@ struct ConfItem #define CONF_FLAGS_EXEMPTDNSBL 0x04000000 #define CONF_FLAGS_EXEMPTPROXY 0x08000000 #define CONF_FLAGS_ALLOW_SCTP 0x10000000 +#define CONF_FLAGS_KLINE_SPOOF 0x20000000 /* Macros for struct ConfItem */ @@ -136,6 +137,7 @@ struct ConfItem #define IsConfExtendChans(x) ((x)->flags & CONF_FLAGS_EXTEND_CHANS) #define IsConfSSLNeeded(x) ((x)->flags & CONF_FLAGS_NEED_SSL) #define IsConfAllowSCTP(x) ((x)->flags & CONF_FLAGS_ALLOW_SCTP) +#define IsConfKlineSpoof(x) ((x)->flags & CONF_FLAGS_KLINE_SPOOF) /* flag definitions for opers now in client.h */ diff --git a/ircd/client.c b/ircd/client.c index 9cc059f8..b333f44e 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -602,13 +602,15 @@ check_one_kline(struct ConfItem *kline) /* match one kline */ switch (masktype) { case HM_IPV4: - if (client_p->localClient->ip.ss_family == AF_INET6 && + case HM_IPV6: + if (IsConfDoSpoofIp(client_p->localClient->att_conf) && + IsConfKlineSpoof(client_p->localClient->att_conf)) + continue; + if (client_p->localClient->ip.ss_family == AF_INET6 && sockaddr.ss_family == AF_INET && rb_ipv4_from_ipv6((struct sockaddr_in6 *)&client_p->localClient->ip, &ip4) && comp_with_mask_sock((struct sockaddr *)&ip4, (struct sockaddr *)&sockaddr, bits)) matched = 1; - /* fallthrough */ - case HM_IPV6: - if (client_p->localClient->ip.ss_family == sockaddr.ss_family && + else if (client_p->localClient->ip.ss_family == sockaddr.ss_family && comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, (struct sockaddr *)&sockaddr, bits)) matched = 1; @@ -616,6 +618,9 @@ check_one_kline(struct ConfItem *kline) case HM_HOST: if (match(kline->host, client_p->orighost)) matched = 1; + if (IsConfDoSpoofIp(client_p->localClient->att_conf) && + IsConfKlineSpoof(client_p->localClient->att_conf)) + continue; if (match(kline->host, client_p->sockhost)) matched = 1; break; diff --git a/ircd/hostmask.c b/ircd/hostmask.c index 580a3509..94214041 100644 --- a/ircd/hostmask.c +++ b/ircd/hostmask.c @@ -383,34 +383,38 @@ find_address_conf(const char *host, const char *sockhost, const char *user, if(IsConfExemptKline(iconf)) return iconf; - /* Find the best K-line... -A1kmm */ - kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL); - - /* If they are K-lined, return the K-line */ - if(kconf) - return kconf; - /* if theres a spoof, check it against klines.. */ if(IsConfDoSpoofIp(iconf)) { char *p = strchr(iconf->info.name, '@'); /* note, we dont need to pass sockhost here, as its - * guaranteed to not match by whats above.. --anfl + * guaranteed to not match by whats below.. --anfl */ if(p) { *p = '\0'; - kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL); + kconf = find_conf_by_address(p+1, NULL, NULL, NULL, CONF_KILL, aftype, iconf->info.name, NULL); *p = '@'; } else - kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL); + kconf = find_conf_by_address(iconf->info.name, NULL, NULL, NULL, CONF_KILL, aftype, vuser, NULL); if(kconf) return kconf; + + /* everything else checks real hosts, if they're kline_spoof_ip we're done */ + if(IsConfKlineSpoof(iconf)) + return iconf; } + /* Find the best K-line... -A1kmm */ + kconf = find_conf_by_address(host, sockhost, NULL, ip, CONF_KILL, aftype, user, NULL); + + /* If they are K-lined, return the K-line */ + if(kconf) + return kconf; + /* if no_tilde, check the username without tilde against klines too * -- jilles */ if(user != vuser) diff --git a/ircd/newconf.c b/ircd/newconf.c index bf87c093..6a81208d 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -353,6 +353,7 @@ static struct mode_table auth_table[] = { {"need_sasl", CONF_FLAGS_NEED_SASL }, {"extend_chans", CONF_FLAGS_EXTEND_CHANS }, {"allow_sctp", CONF_FLAGS_ALLOW_SCTP }, + {"kline_spoof_ip", CONF_FLAGS_KLINE_SPOOF }, {NULL, 0} };