]>
Commit | Line | Data |
---|---|---|
721410d5 SB |
1 | #include "stdinc.h" |
2 | #include "modules.h" | |
3 | #include "hook.h" | |
4 | #include "client.h" | |
5958d6b9 | 5 | #include "hostmask.h" |
721410d5 SB |
6 | #include "ircd.h" |
7 | #include "send.h" | |
8 | #include "hash.h" | |
9 | #include "s_conf.h" | |
10 | #include "s_user.h" | |
11 | #include "s_serv.h" | |
12 | #include "numeric.h" | |
13 | ||
14 | #include <stdint.h> | |
15 | ||
5d5603b6 EK |
16 | static const char sasl_usercloak_desc[] = |
17 | "Insert the SASL account name into certain iline spoofed hosts"; | |
18 | ||
721410d5 SB |
19 | static void check_new_user(void *data); |
20 | mapi_hfn_list_av1 sasl_usercloak_hfnlist[] = { | |
5d5603b6 | 21 | { "new_local_user", check_new_user }, |
721410d5 SB |
22 | { NULL, NULL } |
23 | }; | |
24 | ||
5958d6b9 | 25 | |
721410d5 SB |
26 | unsigned int fnv_hash_string(char *str) |
27 | { | |
28 | unsigned int hash = 0x811c9dc5; // Magic value for 32-bit fnv1 hash initialisation. | |
29 | unsigned char *p = (unsigned char *)str; | |
30 | while (*p) | |
31 | { | |
32 | hash += (hash<<1) + (hash<<4) + (hash<<7) + (hash<<8) + (hash<<24); | |
33 | hash ^= *p++; | |
34 | } | |
35 | return hash; | |
36 | } | |
37 | ||
38 | static void | |
39 | check_new_user(void *vdata) | |
40 | { | |
5d5603b6 | 41 | struct Client *source_p = vdata; |
721410d5 | 42 | |
b6b40dda EK |
43 | if (IsAnyDead(source_p)) |
44 | return; | |
45 | ||
721410d5 SB |
46 | if (!IsIPSpoof(source_p)) |
47 | return; | |
48 | ||
49 | if (EmptyString(source_p->user->suser)) | |
50 | return; | |
51 | ||
cdeca37e EK |
52 | char *accountpart = strstr(source_p->orighost, "/account"); |
53 | if (!accountpart || accountpart[8] != '\0') | |
721410d5 SB |
54 | return; |
55 | ||
cdeca37e EK |
56 | accountpart += 1; |
57 | ||
721410d5 | 58 | char buf[HOSTLEN]; |
271ddd99 | 59 | memset(buf, 0, sizeof(buf)); |
721410d5 SB |
60 | char *dst = buf; |
61 | ||
dae6f5db SB |
62 | strncpy(buf, source_p->orighost, accountpart - source_p->orighost); |
63 | dst += accountpart - source_p->orighost; | |
721410d5 SB |
64 | |
65 | int needhash = 0; | |
66 | ||
67 | for (char *src = source_p->user->suser; *src ; src++ ) | |
68 | { | |
5958d6b9 | 69 | if (dst >= buf + sizeof(buf)) |
721410d5 SB |
70 | { |
71 | /* Doesn't fit. Warn opers and bail. */ | |
72 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, | |
73 | "Couldn't fit account name part %s in hostname for %s!%s@%s", | |
dae6f5db | 74 | source_p->user->suser, source_p->name, source_p->username, source_p->orighost); |
721410d5 SB |
75 | return; |
76 | } | |
77 | ||
5d5603b6 | 78 | char c = tolower(*src); |
721410d5 SB |
79 | |
80 | if (IsHostChar(c)) | |
81 | *dst++ = c; | |
82 | else | |
83 | needhash = 1; | |
84 | } | |
85 | ||
86 | if (needhash) | |
87 | { | |
88 | if (dst > buf + sizeof(buf) - 12) /* '/x-' plus eight digit hash plus null terminator */ | |
89 | { | |
90 | /* Doesn't fit. Warn opers and bail. */ | |
91 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, | |
92 | "Couldn't fit account name part %s in hostname for %s!%s@%s", | |
dae6f5db | 93 | source_p->user->suser, source_p->name, source_p->username, source_p->orighost); |
721410d5 SB |
94 | return; |
95 | } | |
96 | ||
97 | *dst++ = '/'; | |
98 | *dst++ = 'x'; | |
99 | *dst++ = '-'; | |
100 | ||
101 | unsigned int hashval = fnv_hash_string(source_p->user->suser); | |
102 | hashval %= 100000000; // eight digits only please. | |
b44f6669 | 103 | snprintf(dst, 9, "%08u", hashval); |
721410d5 SB |
104 | } |
105 | ||
106 | /* just in case */ | |
107 | buf[HOSTLEN-1] = '\0'; | |
108 | ||
dae6f5db SB |
109 | /* If hostname has been changed already (probably by services cloak on SASL login), then |
110 | * leave it intact. If not, change it. In either case, update the original hostname. | |
111 | */ | |
112 | if (0 == irccmp(source_p->host, source_p->orighost)) | |
113 | change_nick_user_host(source_p, source_p->name, source_p->username, buf, 0, "Changing host"); | |
114 | strncpy(source_p->orighost, buf, HOSTLEN); | |
5958d6b9 EK |
115 | |
116 | { | |
117 | struct ConfItem *aconf = find_kline(source_p); | |
118 | ||
119 | if(aconf == NULL) | |
120 | return; | |
121 | ||
122 | if(IsExemptKline(source_p)) | |
123 | { | |
124 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, | |
125 | "KLINE over-ruled for %s, client is kline_exempt [%s@%s]", | |
126 | get_client_name(source_p, HIDE_IP), | |
127 | aconf->user, aconf->host); | |
128 | return; | |
129 | } | |
130 | ||
a9227555 | 131 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, |
5958d6b9 EK |
132 | "KLINE active for %s", |
133 | get_client_name(source_p, HIDE_IP)); | |
134 | ||
135 | notify_banned_client(source_p, aconf, K_LINED); | |
136 | } | |
721410d5 | 137 | } |
5d5603b6 EK |
138 | |
139 | DECLARE_MODULE_AV2(sasl_usercloak, NULL, NULL, NULL, NULL, sasl_usercloak_hfnlist, NULL, NULL, sasl_usercloak_desc); |