]>
Commit | Line | Data |
---|---|---|
721410d5 SB |
1 | #include "stdinc.h" |
2 | #include "modules.h" | |
3 | #include "hook.h" | |
4 | #include "client.h" | |
5 | #include "ircd.h" | |
6 | #include "send.h" | |
7 | #include "hash.h" | |
8 | #include "s_conf.h" | |
9 | #include "s_user.h" | |
10 | #include "s_serv.h" | |
11 | #include "numeric.h" | |
12 | ||
13 | #include <stdint.h> | |
14 | ||
15 | static void check_new_user(void *data); | |
16 | mapi_hfn_list_av1 sasl_usercloak_hfnlist[] = { | |
17 | { "new_local_user", (hookfn) check_new_user }, | |
18 | { NULL, NULL } | |
19 | }; | |
20 | ||
21 | DECLARE_MODULE_AV1(sasl_usercloak, NULL, NULL, NULL, NULL, | |
22 | sasl_usercloak_hfnlist, "$Revision: 3526 $"); | |
23 | ||
24 | unsigned int fnv_hash_string(char *str) | |
25 | { | |
26 | unsigned int hash = 0x811c9dc5; // Magic value for 32-bit fnv1 hash initialisation. | |
27 | unsigned char *p = (unsigned char *)str; | |
28 | while (*p) | |
29 | { | |
30 | hash += (hash<<1) + (hash<<4) + (hash<<7) + (hash<<8) + (hash<<24); | |
31 | hash ^= *p++; | |
32 | } | |
33 | return hash; | |
34 | } | |
35 | ||
36 | static void | |
37 | check_new_user(void *vdata) | |
38 | { | |
39 | struct Client *source_p = (void *)vdata; | |
40 | ||
41 | if (!IsIPSpoof(source_p)) | |
42 | return; | |
43 | ||
44 | if (EmptyString(source_p->user->suser)) | |
45 | return; | |
46 | ||
47 | char *accountpart = strstr(source_p->host, "account"); | |
48 | if (!accountpart) | |
49 | return; | |
50 | ||
51 | char buf[HOSTLEN]; | |
52 | char *dst = buf; | |
53 | ||
54 | strncpy(buf, source_p->host, accountpart - source_p->host); | |
55 | dst += accountpart - source_p->host; | |
56 | ||
57 | int needhash = 0; | |
58 | ||
59 | for (char *src = source_p->user->suser; *src ; src++ ) | |
60 | { | |
61 | if (dst > buf + sizeof(buf)) | |
62 | { | |
63 | /* Doesn't fit. Warn opers and bail. */ | |
64 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, | |
65 | "Couldn't fit account name part %s in hostname for %s!%s@%s", | |
66 | source_p->user->suser, source_p->name, source_p->username, source_p->host); | |
67 | return; | |
68 | } | |
69 | ||
70 | char c = ToLower(*src); | |
71 | ||
72 | if (IsHostChar(c)) | |
73 | *dst++ = c; | |
74 | else | |
75 | needhash = 1; | |
76 | } | |
77 | ||
78 | if (needhash) | |
79 | { | |
80 | if (dst > buf + sizeof(buf) - 12) /* '/x-' plus eight digit hash plus null terminator */ | |
81 | { | |
82 | /* Doesn't fit. Warn opers and bail. */ | |
83 | sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, | |
84 | "Couldn't fit account name part %s in hostname for %s!%s@%s", | |
85 | source_p->user->suser, source_p->name, source_p->user, source_p->host); | |
86 | return; | |
87 | } | |
88 | ||
89 | *dst++ = '/'; | |
90 | *dst++ = 'x'; | |
91 | *dst++ = '-'; | |
92 | ||
93 | unsigned int hashval = fnv_hash_string(source_p->user->suser); | |
94 | hashval %= 100000000; // eight digits only please. | |
95 | snprintf(dst, 9, "%08ud", hashval); | |
96 | } | |
97 | ||
98 | /* just in case */ | |
99 | buf[HOSTLEN-1] = '\0'; | |
100 | ||
101 | change_nick_user_host(source_p, source_p->name, source_p->username, buf, 0, "Changing host"); | |
102 | } |