10 #define AUTHLOG "auth"
12 enum{ R_AccessRequest=1, /* Packet code */
24 typedef struct Secret{
29 typedef struct Attribute{
30 struct Attribute *next;
32 uchar len; // number of bytes in value
36 typedef struct Packet{
38 uchar authenticator[16];
42 // assumes pass is at most 16 chars
44 hide(Secret *shared, uchar *auth, Secret *pass, uchar *x)
49 M = md5(shared->s, shared->len, nil, nil);
53 for(i = 0; i < n; i++)
58 authcmp(Secret *shared, uchar *buf, int m, uchar *auth)
63 M = md5(buf, 4, nil, nil); // Code+ID+Length
64 M = md5(auth, 16, nil, M); // RequestAuth
65 M = md5(buf+20, m-20, nil, M); // Attributes
66 md5(shared->s, shared->len, x, M);
67 return memcmp(x, buf+4, 16);
71 newRequest(uchar *auth)
76 p = (Packet*)malloc(sizeof(*p));
79 p->code = R_AccessRequest;
81 memmove(p->authenticator, auth, 16);
104 ding(void *v, char *msg)
107 /* syslog(0, AUTHLOG, "ding %s", msg); */
108 if(strstr(msg, "alarm"))
114 rpc(char *dest, Secret *shared, Packet *req)
116 uchar buf[4096], buf2[4096], *b, *e;
122 e = buf + sizeof buf;
125 memmove(buf+4, req->authenticator, 16);
127 for(a = &req->first; a; a = a->next){
128 if(b + 2 + a->len > e)
132 memmove(b, a->val, a->len);
139 // send request, wait for reply
140 fd = dial(dest, 0, 0, 0);
142 syslog(0, AUTHLOG, "%s: rpc can't get udp channel", dest);
147 for(try = 0; try < 2; try++){
149 m = write(fd, buf, n);
151 syslog(0, AUTHLOG, "%s: rpc write err %d %d: %r", dest, m, n);
155 m = read(fd, buf2, sizeof buf2);
158 syslog(0, AUTHLOG, "%s rpc read err %d: %r", dest, m);
161 if(m == 0 || buf2[1] != buf[1]){ // need matching ID
162 syslog(0, AUTHLOG, "%s unmatched reply %d", dest, m);
165 if(authcmp(shared, buf2, m, buf+4) == 0)
167 syslog(0, AUTHLOG, "%s bad rpc chksum", dest);
176 resp = (Packet*)malloc(sizeof(*resp));
184 syslog(0, AUTHLOG, "rpc got %d bytes, length said %d", m, n);
188 memmove(resp->authenticator, b, 16);
199 if(b + a->len > e){ // corrupt packet
204 memmove(a->val, b, a->len);
206 if(b < e){ // any more attributes?
207 a->next = (Attribute*)malloc(sizeof(*a));
219 setAttribute(Packet *p, uchar type, uchar *s, int n)
225 a = (Attribute*)malloc(sizeof(*a));
228 a->next = p->first.next;
233 if(a->len > 253 ) // RFC2138, section 5
235 memmove(a->val, s, a->len);
239 /* return a reply message attribute string */
244 static char buf[255];
246 for(a = &p->first; a; a = a->next){
247 if(a->type == R_ReplyMessage){
248 if(a->len >= sizeof buf)
249 a->len = sizeof(buf)-1;
250 memmove(buf, a->val, a->len);
257 /* for convenience while debugging */
259 Attribute *stateattr;
267 uchar *au = p->authenticator;
271 e = pbuf + sizeof(pbuf);
273 np = seprint(pbuf, e, "Packet ID=%d auth=%x %x %x... ", p->ID, au[0], au[1], au[2]);
275 case R_AccessRequest:
276 np = seprint(np, e, "request\n");
279 np = seprint(np, e, "accept\n");
282 np = seprint(np, e, "reject\n");
284 case R_AccessChallenge:
285 np = seprint(np, e, "challenge\n");
288 np = seprint(np, e, "code=%d\n", p->code);
291 replymess = "0000000";
292 for(a = &p->first; a; a = a->next){
295 memmove(buf, a->val, a->len);
296 np = seprint(np, e, " [%d]", a->type);
297 for(i = 0; i<a->len; i++)
298 if(isprint(a->val[i]))
299 np = seprint(np, e, "%c", a->val[i]);
301 np = seprint(np, e, "\\%o", a->val[i]);
302 np = seprint(np, e, "\n");
304 if(a->type == R_ReplyMessage)
305 replymess = strdup(buf);
306 else if(a->type == R_State)
310 syslog(0, AUTHLOG, "%s", pbuf);
320 ifc = readipifc("/net", ifc, -1);
321 for(nifc = ifc; nifc; nifc = nifc->next)
322 for(lifc = nifc->lifc; lifc; lifc = lifc->next)
323 if(ipcmp(lifc->ip, IPnoaddr) != 0 && ipcmp(lifc->ip, v4prefix) != 0)
330 /* returns 0 on success, error message on failure */
332 secureidcheck(char *user, char *response)
334 Packet *req = nil, *resp = nil;
339 char dest[3*IPaddrlen+20];
341 char *rv = "authentication failed";
343 Ndbtuple *t, *nt, *tt;
350 /* bad responses make them disable the fob, avoid silly checks */
351 if(strlen(response) < 4 || strpbrk(response,"abcdefABCDEF") != nil)
354 /* get radius secret */
355 radiussecret = ndbgetvalue(db, &s, "radius", "lra-radius", "secret", &t);
356 if(radiussecret == nil){
357 syslog(0, AUTHLOG, "secureidcheck: nil radius secret: %r");
361 /* translate user name if we have to */
363 for(nt = t; nt; nt = nt->entry){
364 if(strcmp(nt->attr, "uid") == 0 && strcmp(nt->val, user) == 0)
365 for(tt = nt->line; tt != nt; tt = tt->line)
366 if(strcmp(tt->attr, "rid") == 0){
367 strcpy(ruser, tt->val);
377 req = newRequest((uchar*)u);
380 shared.s = (uchar*)radiussecret;
381 shared.len = strlen(radiussecret);
384 syslog(0, AUTHLOG, "no interfaces: %r\n");
387 if(setAttribute(req, R_NASIPAddress, ip + IPv4off, 4) < 0)
390 if(setAttribute(req, R_UserName, (uchar*)ruser, strlen(ruser)) < 0)
392 pass.s = (uchar*)response;
393 pass.len = strlen(response);
394 hide(&shared, req->authenticator, &pass, x);
395 if(setAttribute(req, R_UserPassword, x, 16) < 0)
398 t = ndbsearch(netdb, &s, "sys", "lra-radius");
400 syslog(0, AUTHLOG, "secureidcheck: nil radius sys search: %r\n");
403 for(nt = t; nt; nt = nt->entry){
404 if(strcmp(nt->attr, "ip") != 0)
407 snprint(dest,sizeof dest,"udp!%s!oradius", nt->val);
408 resp = rpc(dest, &shared, req);
410 syslog(0, AUTHLOG, "%s nil response", dest);
413 if(resp->ID != req->ID){
414 syslog(0, AUTHLOG, "%s mismatched ID req=%d resp=%d",
415 dest, req->ID, resp->ID);
423 syslog(0, AUTHLOG, "%s accepted ruser=%s", dest, ruser);
427 syslog(0, AUTHLOG, "%s rejected ruser=%s %s", dest, ruser, replymsg(resp));
428 rv = "secureid failed";
430 case R_AccessChallenge:
431 syslog(0, AUTHLOG, "%s challenge ruser=%s %s", dest, ruser, replymsg(resp));
432 rv = "secureid out of sync";
435 syslog(0, AUTHLOG, "%s code=%d ruser=%s %s", dest, resp->code, ruser, replymsg(resp));
438 break; // we have a proper reply, no need to ask again