]> jfr.im git - irc/quakenet/newserv.git/blame - authext/authext.c
CHANSERV: better batcher error handling for expired accounts/accounts with no email.
[irc/quakenet/newserv.git] / authext / authext.c
CommitLineData
57583275 1#include "authext.h"
2#include "../core/nsmalloc.h"
3#include "../core/error.h"
4#include "../lib/sstring.h"
5#include "../lib/irc_string.h"
5a335041 6#include "../nick/nick.h"
d40ae845 7#include "../core/hooks.h"
1a96a370 8#include "../lib/strlfunc.h"
240bbd21 9#include "../lib/version.h"
4208eafd 10#include "../lib/ccassert.h"
57583275 11
12#include <string.h>
d40ae845 13#include <stdio.h>
57583275 14
240bbd21
CP
15MODULE_VERSION("")
16
4208eafd
GB
17/* checking to see that u_int64_t == unsigned long long for strtoull */
18CCASSERT(sizeof(unsigned long long) == sizeof(u_int64_t))
19
57583275 20#define authnamehash(x) ((x)%AUTHNAMEHASHSIZE)
729c4971 21#define authnamehashbyname(x) (irc_crc32i(x)%AUTHNAMEHASHSIZE)
57583275 22
57583275 23authname *authnametable[AUTHNAMEHASHSIZE];
24
5a335041
CP
25/* internal access only */
26static authname *authnametablebyname[AUTHNAMEHASHSIZE];
27
04b12064
CP
28static struct {
29 sstring *name;
bbf9de81 30 int persistent;
04b12064 31} authnameexts[MAXAUTHNAMEEXTS];
57583275 32
d40ae845
CP
33static void authextstats(int hooknum, void *arg);
34
5a335041 35void _init(void) {
57583275 36 memset(authnametable,0,sizeof(authnametable));
5a335041 37 memset(authnametablebyname,0,sizeof(authnametablebyname));
d40ae845 38 registerhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 39}
40
5a335041 41void _fini(void) {
d40ae845 42 deregisterhook(HOOK_CORE_STATSREQUEST, &authextstats);
57583275 43 nsfreeall(POOL_AUTHEXT);
44}
45
5a335041 46authname *newauthname(void) {
be78a174 47 return nsmalloc(POOL_AUTHEXT, sizeof(authname));
57583275 48}
49
50void freeauthname (authname *anp) {
be78a174 51 nsfree(POOL_AUTHEXT, anp);
57583275 52}
53
bbf9de81 54int registerauthnameext(const char *name, int persistent) {
57583275 55 int i;
56
57 if (findauthnameext(name)!=-1) {
58 Error("nick",ERR_WARNING,"Tried to register duplicate authname extension %s",name);
59 return -1;
60 }
61
62 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064
CP
63 if (authnameexts[i].name==NULL) {
64 authnameexts[i].name=getsstring(name,100);
bbf9de81 65 authnameexts[i].persistent=persistent;
57583275 66 return i;
67 }
68 }
69
70 Error("nick",ERR_WARNING,"Tried to register too many authname extensions: %s",name);
71 return -1;
72}
73
74int findauthnameext(const char *name) {
75 int i;
76
77 for (i=0;i<MAXAUTHNAMEEXTS;i++) {
04b12064 78 if (authnameexts[i].name!=NULL && !ircd_strcmp(name,authnameexts[i].name->content)) {
57583275 79 return i;
80 }
81 }
82
83 return -1;
84}
85
86void releaseauthnameext(int index) {
87 int i;
88 authname *anp;
89
04b12064
CP
90 freesstring(authnameexts[index].name);
91 authnameexts[index].name=NULL;
57583275 92
93 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
94 for (anp=authnametable[i];anp;anp=anp->next) {
95 anp->exts[index]=NULL;
96 }
97 }
5a335041
CP
98
99 /* the contents of authnametablebyname should be identical */
57583275 100}
101
102authname *findauthname(unsigned long userid) {
103 authname *anp;
104
105 if(!userid)
106 return NULL;
107
108 for (anp=authnametable[authnamehash(userid)];anp;anp=(authname *)anp->next)
109 if (userid==anp->userid)
110 return anp;
111
112 return NULL;
113}
114
5a335041 115authname *findauthnamebyname(const char *name) {
57583275 116 authname *anp;
57583275 117
5a335041
CP
118 if(!name)
119 return NULL;
120
d40ae845 121 for (anp=authnametablebyname[authnamehashbyname(name)];anp;anp=(authname *)anp->nextbyname)
1a96a370 122 if (!ircd_strcmp(anp->name, name))
5a335041
CP
123 return anp;
124
125 return NULL;
126}
127
128authname *findorcreateauthname(unsigned long userid, const char *name) {
129 authname *anp;
130 unsigned int thehash=authnamehash(userid), secondhash = authnamehashbyname(name);
131
132 if(!userid || !name)
57583275 133 return NULL;
134
135 for (anp=authnametable[thehash];anp;anp=(authname *)anp->next)
136 if (userid==anp->userid)
137 return anp;
138
139 anp=newauthname();
140 anp->userid=userid;
1a96a370 141 strlcpy(anp->name, name, sizeof(anp->name));
57583275 142 anp->usercount=0;
143 anp->marker=0;
0b0fb773 144 anp->flags=0;
57583275 145 anp->nicks=NULL;
146 memset(anp->exts, 0, MAXAUTHNAMEEXTS * sizeof(void *));
147 anp->next=(struct authname *)authnametable[thehash];
148 authnametable[thehash]=anp;
149
5a335041
CP
150 anp->namebucket=secondhash;
151 anp->nextbyname=(struct authname *)authnametablebyname[secondhash];
152 authnametablebyname[secondhash]=anp;
153
57583275 154 return anp;
155}
156
157void releaseauthname(authname *anp) {
158 authname **manp;
5a335041 159 int i, found;
57583275 160 if (anp->usercount==0) {
1cf62143
CP
161 anp->nicks = NULL;
162
57583275 163 for(i=0;i<MAXAUTHNAMEEXTS;i++)
bbf9de81 164 if(authnameexts[i].persistent && anp->exts[i]!=NULL)
57583275 165 return;
166
04b12064 167 triggerhook(HOOK_AUTH_LOSTAUTHNAME, (void *)anp);
5a335041 168 found = 0;
57583275 169 for(manp=&(authnametable[authnamehash(anp->userid)]);*manp;manp=(authname **)&((*manp)->next)) {
5a335041
CP
170 if ((*manp)==anp) {
171 (*manp)=(authname *)anp->next;
172 found = 1;
173 break;
174 }
175 }
176 if(!found) {
177 Error("nick",ERR_ERROR,"Unable to remove authname %lu from hashtable",anp->userid);
178 return;
179 }
180
4884107a 181 for(manp=&(authnametablebyname[anp->namebucket]);*manp;manp=(authname **)&((*manp)->nextbyname)) {
57583275 182 if ((*manp)==anp) {
4884107a 183 (*manp)=(authname *)anp->nextbyname;
57583275 184 freeauthname(anp);
185 return;
186 }
187 }
5a335041 188
4884107a 189 Error("nick",ERR_STOP,"Unable to remove authname %lu from byname hashtable, TABLES ARE INCONSISTENT -- DYING",anp->userid);
57583275 190 }
191}
192
5a335041 193unsigned int nextauthnamemarker(void) {
57583275 194 int i;
195 authname *anp;
196 static unsigned int authnamemarker=0;
197
198 authnamemarker++;
199 if (!authnamemarker) {
200 /* If we wrapped to zero, zap the marker on all records */
201 for (i=0;i<AUTHNAMEHASHSIZE;i++)
202 for (anp=authnametable[i];anp;anp=anp->next)
203 anp->marker=0;
204 authnamemarker++;
205 }
206
207 return authnamemarker;
208}
1cf62143
CP
209
210authname *getauthbyname(const char *name) {
211 authname *a = findauthnamebyname(name);
212 if(!a || !a->nicks)
213 return NULL;
214
215 return a;
216}
217
cdc9e13c 218static char *genstats(authname **hashtable, authname *(nextfn)(authname *)) {
d40ae845
CP
219 int i,curchain,maxchain=0,total=0,buckets=0;
220 authname *ap;
221 static char buf[100];
222
223 for (i=0;i<AUTHNAMEHASHSIZE;i++) {
224 if (hashtable[i]!=NULL) {
225 buckets++;
226 curchain=0;
cdc9e13c 227 for (ap=hashtable[i];ap;ap=nextfn(ap)) {
d40ae845
CP
228 total++;
229 curchain++;
230 }
231 if (curchain>maxchain) {
232 maxchain=curchain;
233 }
234 }
235 }
236
237 snprintf(buf, sizeof(buf), "%6d authexts (HASH: %6d/%6d, chain %3d)",total,buckets,AUTHNAMEHASHSIZE,maxchain);
238 return buf;
239}
240
cdc9e13c
CP
241static authname *nextbynext(authname *in) {
242 return in->next;
243}
244
245static authname *nextbyname(authname *in) {
246 return in->nextbyname;
247}
248
d40ae845
CP
249static void authextstats(int hooknum, void *arg) {
250 long level=(long)arg;
251 char buf[100];
252
253 if (level>5) {
254 /* Full stats */
cdc9e13c 255 snprintf(buf,sizeof(buf),"Authext : by id: %s", genstats(authnametable, nextbynext));
d40ae845
CP
256 triggerhook(HOOK_CORE_STATSREPLY,buf);
257
cdc9e13c 258 snprintf(buf,sizeof(buf),"Authext : by name: %s", genstats(authnametablebyname, nextbyname));
d40ae845
CP
259 triggerhook(HOOK_CORE_STATSREPLY,buf);
260 }
261}
262