void main(void) { mpint *z = mpnew(0); mpint *p = mpnew(0); mpint *q = mpnew(0); mpint *nine = mpnew(0); fmtinstall('B', mpconv); strtomp("2492491", nil, 16, z); // 38347921 = x*y = (2**28-9)/7, // an example of 3**(n-1)=1 mod n strtomp("15662C00E811", nil, 16, p);// 23528569104401, a prime uitomp(9, nine); if(probably_prime(z, 5) == 1) fprint(2, "tricked primality test\n"); if(probably_prime(nine, 5) == 1) fprint(2, "9 passed primality test!\n"); if(probably_prime(p, 25) == 1) fprint(2, "ok\n"); DSAprimes(q, p, nil); print("q=%B\np=%B\n", q, p); exits(0); }
static int parsepubkey(char *s, RSApub *key, char **sp, int base) { int n; char *host, *p, *z; z = nil; n = strtoul(s, &p, 10); host = nil; if(n < Arbsz || !isspace(*p)){ /* maybe this is a host name */ host = s; s = strpbrk(s, " \t"); if(s == nil) return -1; z = s; *s++ = '\0'; s += strspn(s, " \t"); n = strtoul(s, &p, 10); if(n < Arbsz || !isspace(*p)){ if(z) *z = ' '; return -1; } } /* Arbsz is just a sanity check */ if((key->ek = strtomp(p, &p, base, nil)) == nil || (key->n = strtomp(p, &p, base, nil)) == nil || (*p != '\0' && !isspace(*p)) || mpsignif(key->n) < Arbsz) { mpfree(key->ek); mpfree(key->n); key->ek = nil; key->n = nil; if(z) *z = ' '; return -1; } if(host == nil){ if(*p != '\0'){ p += strspn(p, " \t"); if(*p != '\0'){ host = emalloc9p(strlen(p)+1); strcpy(host, p); } } free(s); } *sp = host; return 0; }
static int listkeys(Key **kp) { Biobuf *b; Key *k; int nk; char *p, *f[20]; int nf; mpint *mod, *ek; *kp = nil; if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil) return -1; k = nil; nk = 0; while((p = Brdline(b, '\n')) != nil){ p[Blinelen(b)-1] = '\0'; nf = tokenize(p, f, nelem(f)); if(nf == 0 || strcmp(f[0], "key") != 0) continue; p = find(f, nf, "proto"); if(p == nil || strcmp(p, "rsa") != 0) continue; p = find(f, nf, "n"); if(p == nil || (mod = strtomp(p, nil, 16, nil)) == nil) continue; p = find(f, nf, "ek"); if(p == nil || (ek = strtomp(p, nil, 16, nil)) == nil){ mpfree(mod); continue; } p = find(f, nf, "comment"); if(p == nil) p = ""; k = erealloc(k, (nk+1)*sizeof(k[0])); k[nk].mod = mod; k[nk].ek = ek; k[nk].comment = emalloc(strlen(p)+1); strcpy(k[nk].comment, p); nk++; } Bterm(b); *kp = k; return nk; }
static mpint* rpcdecrypt(AuthRpc *rpc, mpint *b) { mpint *a; char *p; p = mptoa(b, 16, nil, 0); if(auth_rpc(rpc, "write", p, strlen(p)) != ARok) sysfatal("factotum rsa write: %r"); free(p); if(auth_rpc(rpc, "read", nil, 0) != ARok) sysfatal("factotum rsa read: %r"); a = strtomp(rpc->arg, nil, 16, nil); mpfree(b); return a; }
static mpint* halfpt(ECdomain *dom, char *s, char **rptr, mpint *out) { char *buf, *r; int n; mpint *ret; n = ((mpsignif(dom->p)+7)/8)*2; if(strlen(s) < n) return 0; buf = malloc(n+1); buf[n] = 0; memcpy(buf, s, n); ret = strtomp(buf, &r, 16, out); *rptr = s + (r - buf); free(buf); return ret; }
void testshift(char *str) { mpint *b1, *b2; int i; b1 = strtomp(str, nil, 16, nil); malloccheck(); fprint(2, "A"); b2 = mpnew(0); fprint(2, "B"); malloccheck(); mpleft(b1, 20, b2); fprint(2, "C"); malloccheck(); mpfree(b1); fprint(2, "D"); malloccheck(); mpfree(b2); }
void consparse(Const *c, char *s) { char t0[512], t1[512]; char yc; char *p; int i, sz, b; memset(c, 0, sizeof(Const)); if(strchr(s, '\'') == nil){ c->n = strtomp(s, &p, 10, nil); if(c->n == nil) c->n = mpnew(0); c->x = mpnew(0); c->sign = 1; if(*p != 0){ snope: b = 0; i = p - s; goto nope; } return; } if(*s != '\''){ sz = strtol(s, &p, 10); if(*p != '\'') goto snope; s = p; }else sz = 0; s++; if(*s == 's' || *s == 'S'){ c->sign = 1; s++; } switch(*s){ case 'h': case 'H': b = 16; break; case 'd': case 'D': b = 10; break; case 'o': case 'O': b = 8; break; case 'b': case 'B': b = 2; break; default: error(nil, "'%c' invalid base specifier", *s); goto out; } c->base = b; s++; if(s[1] == 0 && (s[0] == 'x' || s[0] == 'X' || s[0] == 'z' || s[0] == 'Z' || s[0] == '?')) b = 2; switch(b){ default: yc = '1'; break; case 8: yc = '7'; break; case 16: yc = 'f'; break; } for(i = 0; s[i] != 0; i++){ if(s[i] == 'x' || s[i] == 'X'){ t0[i] = '0'; t1[i] = yc; if(b == 10) goto nope; }else if(s[i] == 'z' || s[i] == 'Z' || s[i] == '?'){ t0[i] = yc; t1[i] = yc; if(b == 10) goto nope; }else{ switch(b){ case 2: if(s[i] > '1') goto nope; break; case 8: if(s[i] > '7') goto nope; break; case 10: if(s[i] > '9') goto nope; break; case 16: if(!isxdigit(s[i])) goto nope; break; } t0[i] = s[i]; t1[i] = '0'; } } t0[i] = 0; t1[i] = 0; switch(b){ default: c->sz = i; break; case 8: c->sz = i * 3; break; case 16: c->sz = i * 4; break; } c->n = strtomp(t0, nil, b, nil); c->x = strtomp(t1, nil, b, nil); if(s[0] == 'x' || s[0] == 'X' || s[0] == 'z' || s[0] == 'Z' || s[0] == '?'){ mpxtend(c->n, c->sz, c->n); mpxtend(c->x, c->sz, c->x); } if(c->n == nil) c->n = mpnew(0); if(c->x == nil) c->x = mpnew(0); if(sz != 0) if((b & 1) != 0){ mpxtend(c->n, sz, c->n); mpxtend(c->x, sz, c->x); }else{ mptrunc(c->n, sz, c->n); mptrunc(c->x, sz, c->x); } c->sz = sz; return; nope: error(nil, "'%c' in %s number", s[i], b == 8 ? "octal": b == 16 ? "hexadecimal" : b == 2 ? "binary" : "decimal"); out: c->n = mpnew(0); c->x = mpnew(0); c->sz = 0; }
static int authrsafn(Conn *c) { uint8_t chalbuf[32+SESSIDLEN], response[MD5dlen]; char *s, *p; int afd, ret; AuthRpc *rpc; Msg *m; mpint *chal, *decr, *unpad, *mod; debug(DBG_AUTH, "rsa!\n"); if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ debug(DBG_AUTH, "open /mnt/factotum/rpc: %r\n"); return -1; } if((rpc = auth_allocrpc(afd)) == nil){ debug(DBG_AUTH, "auth_allocrpc: %r\n"); close(afd); return -1; } s = "proto=rsa role=client"; if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){ debug(DBG_AUTH, "auth_rpc start %s failed: %r\n", s); auth_freerpc(rpc); close(afd); return -1; } ret = -1; debug(DBG_AUTH, "trying factotum rsa keys\n"); while(auth_rpc(rpc, "read", nil, 0) == ARok){ debug(DBG_AUTH, "try %s\n", (char*)rpc->arg); mod = strtomp(rpc->arg, nil, 16, nil); m = allocmsg(c, SSH_CMSG_AUTH_RSA, 16+(mpsignif(mod)+7/8)); putmpint(m, mod); sendmsg(m); mpfree(mod); m = recvmsg(c, -1); switch(m->type){ case SSH_SMSG_FAILURE: debug(DBG_AUTH, "\tnot accepted %s\n", (char*)rpc->arg); free(m); continue; default: badmsg(m, 0); case SSH_SMSG_AUTH_RSA_CHALLENGE: break; } chal = getmpint(m); debug(DBG_AUTH, "\tgot challenge %B\n", chal); free(m); p = mptoa(chal, 16, nil, 0); mpfree(chal); if(p == nil){ debug(DBG_AUTH, "\tmptoa failed: %r\n"); unpad = mpnew(0); goto Keepgoing; } if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){ debug(DBG_AUTH, "\tauth_rpc write failed: %r\n"); free(p); unpad = mpnew(0); /* it will fail, we'll go round again */ goto Keepgoing; } free(p); if(auth_rpc(rpc, "read", nil, 0) != ARok){ debug(DBG_AUTH, "\tauth_rpc read failed: %r\n"); unpad = mpnew(0); goto Keepgoing; } decr = strtomp(rpc->arg, nil, 16, nil); debug(DBG_AUTH, "\tdecrypted %B\n", decr); unpad = rsaunpad(decr); debug(DBG_AUTH, "\tunpadded %B\n", unpad); mpfree(decr); Keepgoing: mptoberjust(unpad, chalbuf, 32); mpfree(unpad); debug(DBG_AUTH, "\trjusted %.*H\n", 32, chalbuf); memmove(chalbuf+32, c->sessid, SESSIDLEN); debug(DBG_AUTH, "\tappend sesskey %.*H\n", 32, chalbuf); md5(chalbuf, 32+SESSIDLEN, response, nil); m = allocmsg(c, SSH_CMSG_AUTH_RSA_RESPONSE, MD5dlen); putbytes(m, response, MD5dlen); sendmsg(m); m = recvmsg(c, -1); switch(m->type){ case SSH_SMSG_FAILURE: free(m); continue; default: badmsg(m, 0); case SSH_SMSG_SUCCESS: break; } ret = 0; break; } auth_freerpc(rpc); close(afd); return ret; }
static int dologin(int fd, char *S, int forceSTA) { int i, n, rv; char *file, *mess, *nl; char msg[Maxmsg+1]; PW *pw; SConn *conn; pw = nil; rv = -1; /* collect the first message */ if((conn = newSConn(fd)) == nil) return -1; if(readstr(conn, msg) < 0){ fprint(2, "secstored: remote: %s: %r\n", msg); writerr(conn, "can't read your first message"); goto Out; } /* authenticate */ if(PAKserver(conn, S, msg, &pw) < 0){ if(pw != nil) syslog(0, LOG, "secstore denied for %s", pw->id); goto Out; } if((forceSTA || pw->status&STA) != 0){ conn->write(conn, (uchar*)"STA", 3); if(readstr(conn, msg) < 10 || strncmp(msg, "STA", 3) != 0){ syslog(0, LOG, "no STA from %s", pw->id); goto Out; } mess = secureidcheck(pw->id, msg+3); if(mess != nil){ syslog(0, LOG, "secureidcheck denied %s because %s", pw->id, mess); goto Out; } } conn->write(conn, (uchar*)"OK", 2); syslog(0, LOG, "AUTH %s", pw->id); /* perform operations as asked */ while((n = readstr(conn, msg)) > 0){ if(nl = strchr(msg, '\n')) *nl = 0; syslog(0, LOG, "[%s] %s", pw->id, msg); if(strncmp(msg, "GET ", 4) == 0){ file = validatefile(msg+4); if(file==nil || getfile(conn, pw->id, file) < 0) goto Err; }else if(strncmp(msg, "PUT ", 4) == 0){ file = validatefile(msg+4); if(file==nil || putfile(conn, pw->id, file) < 0){ syslog(0, LOG, "failed PUT %s/%s", pw->id, file); goto Err; } }else if(strncmp(msg, "RM ", 3) == 0){ file = validatefile(msg+3); if(file==nil || removefile(conn, pw->id, file) < 0){ syslog(0, LOG, "failed RM %s/%s", pw->id, file); goto Err; } }else if(strncmp(msg, "CHPASS", 6) == 0){ if(readstr(conn, msg) < 0){ syslog(0, LOG, "protocol botch CHPASS for %s", pw->id); writerr(conn, "protocol botch while setting PAK"); goto Out; } pw->Hi = strtomp(msg, nil, 64, pw->Hi); for(i=0; i < 4 && putPW(pw) < 0; i++) syslog(0, LOG, "password change failed for %s (%d): %r", pw->id, i); if(i==4) goto Out; }else if(strncmp(msg, "BYE", 3) == 0){ rv = 0; break; }else{ writerr(conn, "unrecognized operation"); break; } } if(n <= 0) syslog(0, LOG, "%s closed connection without saying goodbye", pw->id); Out: freePW(pw); conn->free(conn); return rv; Err: writerr(conn, "operation failed"); goto Out; }
void sshserverhandshake(Conn *c) { char *p, buf[128]; Biobuf *b; Attr *a; int i, afd; mpint *m; AuthRpc *rpc; RSApub *key; /* * BUG: should use `attr' to get the key attributes * after the read, but that's not implemented yet. */ if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil) sysfatal("open /mnt/factotum/ctl: %r"); while((p = Brdline(b, '\n')) != nil){ p[Blinelen(b)-1] = '\0'; if(strstr(p, " proto=rsa ") && strstr(p, " service=sshserve ")) break; } if(p == nil) sysfatal("no sshserve keys found in /mnt/factotum/ctl"); a = _parseattr(p); Bterm(b); key = emalloc(sizeof(*key)); if((p = _strfindattr(a, "n")) == nil) sysfatal("no n in sshserve key"); if((key->n = strtomp(p, &p, 16, nil)) == nil || *p != 0) sysfatal("bad n in sshserve key"); if((p = _strfindattr(a, "ek")) == nil) sysfatal("no ek in sshserve key"); if((key->ek = strtomp(p, &p, 16, nil)) == nil || *p != 0) sysfatal("bad ek in sshserve key"); _freeattr(a); if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) sysfatal("open /mnt/factotum/rpc: %r"); if((rpc = auth_allocrpc(afd)) == nil) sysfatal("auth_allocrpc: %r"); p = "proto=rsa role=client service=sshserve"; if(auth_rpc(rpc, "start", p, strlen(p)) != ARok) sysfatal("auth_rpc start %s: %r", p); if(auth_rpc(rpc, "read", nil, 0) != ARok) sysfatal("auth_rpc read: %r"); m = strtomp(rpc->arg, nil, 16, nil); if(mpcmp(m, key->n) != 0) sysfatal("key in /mnt/factotum/ctl does not match rpc key"); mpfree(m); c->hostkey = key; /* send id string */ fprint(c->fd[0], "SSH-1.5-Plan9\n"); /* receive id string */ if(readstrnl(c->fd[0], buf, sizeof buf) < 0) sysfatal("reading server version: %r"); /* id string is "SSH-m.n-comment". We need m=1, n>=5. */ if(strncmp(buf, "SSH-", 4) != 0 || strtol(buf+4, &p, 10) != 1 || *p != '.' || strtol(p+1, &p, 10) < 5 || *p != '-') sysfatal("protocol mismatch; got %s, need SSH-1.x for x>=5", buf); for(i=0; i<COOKIELEN; i++) c->cookie[i] = fastrand(); calcsessid(c); send_ssh_smsg_public_key(c); recv_ssh_cmsg_session_key(c, rpc); auth_freerpc(rpc); close(afd); c->cstate = (*c->cipher->init)(c, 1); /* turns on encryption */ sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0)); authsrvuser(c); }
RSApriv* getkey(int argc, char **argv, int needprivate, Attr **pa) { char *file, *s, *p; int sz; RSApriv *key; Biobuf *b; int regen; Attr *a; if(argc == 0) file = "#d/0"; else file = argv[0]; key = mallocz(sizeof(RSApriv), 1); if(key == nil) return nil; if((b = Bopen(file, OREAD)) == nil) { werrstr("open %s: %r", file); return nil; } s = Brdstr(b, '\n', 1); if(s == nil) { werrstr("read %s: %r", file); return nil; } if(strncmp(s, "key ", 4) != 0) { werrstr("bad key format"); return nil; } regen = 0; a = _parseattr(s+4); if(a == nil) { werrstr("empty key"); return nil; } if((p = _strfindattr(a, "proto")) == nil) { werrstr("no proto"); return nil; } if(strcmp(p, "rsa") != 0) { werrstr("proto not rsa"); return nil; } if((p = _strfindattr(a, "ek")) == nil) { werrstr("no ek"); return nil; } if((key->pub.ek = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad ek"); return nil; } if((p = _strfindattr(a, "n")) == nil) { werrstr("no n"); return nil; } if((key->pub.n = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad n"); return nil; } if((p = _strfindattr(a, "size")) == nil) fprint(2, "warning: missing size; will add\n"); else if((sz = strtol(p, &p, 10)) == 0 || *p != 0) fprint(2, "warning: bad size; will correct\n"); else if(sz != mpsignif(key->pub.n)) fprint(2, "warning: wrong size (got %d, expected %d); will correct\n", sz, mpsignif(key->pub.n)); if(!needprivate) goto call; if((p = _strfindattr(a, "!dk")) == nil) { werrstr("no !dk"); return nil; } if((key->dk = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !dk"); return nil; } if((p = _strfindattr(a, "!p")) == nil) { werrstr("no !p"); return nil; } if((key->p = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !p"); return nil; } if((p = _strfindattr(a, "!q")) == nil) { werrstr("no !q"); return nil; } if((key->q = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !q"); return nil; } if((p = _strfindattr(a, "!kp")) == nil) { fprint(2, "warning: no !kp\n"); regen = 1; goto regen; } if((key->kp = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !kp\n"); regen = 1; goto regen; } if((p = _strfindattr(a, "!kq")) == nil) { fprint(2, "warning: no !kq\n"); regen = 1; goto regen; } if((key->kq = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !kq\n"); regen = 1; goto regen; } if((p = _strfindattr(a, "!c2")) == nil) { fprint(2, "warning: no !c2\n"); regen = 1; goto regen; } if((key->c2 = strtomp(p, &p, 16, nil)) == nil || *p != 0) { fprint(2, "warning: bad !c2\n"); regen = 1; goto regen; } regen: if(regen) { RSApriv *k2; k2 = rsafill(key->pub.n, key->pub.ek, key->dk, key->p, key->q); if(k2 == nil) { werrstr("regenerating chinese-remainder parts failed: %r"); return nil; } key = k2; } call: a = _delattr(a, "ek"); a = _delattr(a, "n"); a = _delattr(a, "size"); a = _delattr(a, "!dk"); a = _delattr(a, "!p"); a = _delattr(a, "!q"); a = _delattr(a, "!c2"); a = _delattr(a, "!kp"); a = _delattr(a, "!kq"); if(pa) *pa = a; return key; }
DSApriv* getdsakey(int argc, char **argv, int needprivate, Attr **pa) { char *file, *s, *p; DSApriv *key; Biobuf *b; Attr *a; if(argc == 0) file = "#d/0"; else file = argv[0]; key = mallocz(sizeof(RSApriv), 1); if(key == nil) return nil; if((b = Bopen(file, OREAD)) == nil) { werrstr("open %s: %r", file); return nil; } s = Brdstr(b, '\n', 1); if(s == nil) { werrstr("read %s: %r", file); return nil; } if(strncmp(s, "key ", 4) != 0) { werrstr("bad key format"); return nil; } a = _parseattr(s+4); if(a == nil) { werrstr("empty key"); return nil; } if((p = _strfindattr(a, "proto")) == nil) { werrstr("no proto"); return nil; } if(strcmp(p, "dsa") != 0) { werrstr("proto not dsa"); return nil; } if((p = _strfindattr(a, "p")) == nil) { werrstr("no p"); return nil; } if((key->pub.p = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad p"); return nil; } if((p = _strfindattr(a, "q")) == nil) { werrstr("no q"); return nil; } if((key->pub.q = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad q"); return nil; } if((p = _strfindattr(a, "alpha")) == nil) { werrstr("no alpha"); return nil; } if((key->pub.alpha = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad alpha"); return nil; } if((p = _strfindattr(a, "key")) == nil) { werrstr("no key="); return nil; } if((key->pub.key = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad key="); return nil; } if(!needprivate) goto call; if((p = _strfindattr(a, "!secret")) == nil) { werrstr("no !secret"); return nil; } if((key->secret = strtomp(p, &p, 16, nil)) == nil || *p != 0) { werrstr("bad !secret"); return nil; } call: a = _delattr(a, "p"); a = _delattr(a, "q"); a = _delattr(a, "alpha"); a = _delattr(a, "key"); a = _delattr(a, "!secret"); if(pa) *pa = a; return key; }
static int dorsa(mpint *mod, mpint *exp, mpint *chal, uint8_t chalbuf[32]) { int afd; AuthRpc *rpc; mpint *m; char buf[4096], *p; mpint *decr, *unpad; USED(exp); snprint(buf, sizeof buf, "proto=rsa service=ssh role=client"); if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ debug(DBG_AUTH, "open /mnt/factotum/rpc: %r\n"); return -1; } if((rpc = auth_allocrpc(afd)) == nil){ debug(DBG_AUTH, "auth_allocrpc: %r\n"); close(afd); return -1; } if(auth_rpc(rpc, "start", buf, strlen(buf)) != ARok){ debug(DBG_AUTH, "auth_rpc start failed: %r\n"); Die: auth_freerpc(rpc); close(afd); return -1; } m = nil; debug(DBG_AUTH, "trying factotum rsa keys\n"); while(auth_rpc(rpc, "read", nil, 0) == ARok){ debug(DBG_AUTH, "try %s\n", (char*)rpc->arg); m = strtomp(rpc->arg, nil, 16, nil); if(mpcmp(m, mod) == 0) break; mpfree(m); m = nil; } if(m == nil) goto Die; mpfree(m); p = mptoa(chal, 16, nil, 0); if(p == nil){ debug(DBG_AUTH, "\tmptoa failed: %r\n"); goto Die; } if(auth_rpc(rpc, "write", p, strlen(p)) != ARok){ debug(DBG_AUTH, "\tauth_rpc write failed: %r\n"); free(p); goto Die; } free(p); if(auth_rpc(rpc, "read", nil, 0) != ARok){ debug(DBG_AUTH, "\tauth_rpc read failed: %r\n"); goto Die; } decr = strtomp(rpc->arg, nil, 16, nil); if(decr == nil){ debug(DBG_AUTH, "\tdecr %s failed\n", rpc->arg); goto Die; } debug(DBG_AUTH, "\tdecrypted %B\n", decr); unpad = rsaunpad(decr); if(unpad == nil){ debug(DBG_AUTH, "\tunpad %B failed\n", decr); mpfree(decr); goto Die; } debug(DBG_AUTH, "\tunpadded %B\n", unpad); mpfree(decr); mptoberjust(unpad, chalbuf, 32); mpfree(unpad); auth_freerpc(rpc); close(afd); return 0; }
PW * getPW(char *id, int dead_or_alive) { ulong now = time(0); char *f1, *f2, *oid; /* fields 1, 2 = attribute, value */ Biobuf *bin; PW *pw; oid = id; if((bin = openPW(id, OREAD)) == 0){ id = "FICTITIOUS"; if((bin = openPW(id, OREAD)) == 0){ werrstr("accounts %s and FICTITIOUS do not exist", oid); return nil; } } pw = emalloc(sizeof *pw); pw->id = estrdup(id); pw->status |= Enabled; while( (f1 = Brdline(bin, '\n')) != 0){ f1[Blinelen(bin)-1] = 0; for(f2 = f1; *f2 && *f2 != ' ' && *f2 != '\t'; f2++) ; if(*f2) for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++) ; if(strcmp(f1, "exp") == 0) pw->expire = strtoul(f2, 0, 10); else if(strcmp(f1, "DISABLED") == 0) pw->status &= ~Enabled; else if(strcmp(f1, "STA") == 0) pw->status |= STA; else if(strcmp(f1, "failed") == 0) pw->failed = strtoul(f2, 0, 10); else if(strcmp(f1, "other") == 0) pw->other = estrdup(f2); else if(strcmp(f1, "PAK-Hi") == 0) pw->Hi = strtomp(f2, nil, 64, nil); } Bterm(bin); if(pw->Hi == nil){ werrstr("corrupted account file for %s", pw->id); freePW(pw); return nil; } if(dead_or_alive) return pw; /* return for editing, whether valid now or not */ if(pw->expire != 0 && pw->expire <= now){ /* %.28s excludes ctime's newline */ werrstr("account %s expired at %.28s", pw->id, ctime(pw->expire)); freePW(pw); return nil; } if((pw->status & Enabled) == 0){ werrstr("account %s disabled", pw->id); freePW(pw); return nil; } if(pw->failed < 10) return pw; /* success */ if(now < mtimePW(id)+300){ werrstr("too many failures; try again in five minutes"); freePW(pw); return nil; } pw->failed = 0; putPW(pw); /* reset failed-login-counter after five minutes */ return pw; }
PW * getPW(char *id, int dead_or_alive) { uint now = time(0); Biobuf *bin; PW *pw; char *f1, *f2; /* fields 1, 2 = attribute, value */ if((bin = openPW(id, OREAD)) == 0){ id = "FICTITIOUS"; if((bin = openPW(id, OREAD)) == 0){ werrstr("account does not exist"); return nil; } } pw = emalloc(sizeof(*pw)); pw->id = estrdup(id); pw->status |= Enabled; while( (f1 = Brdline(bin, '\n')) != 0){ f1[Blinelen(bin)-1] = 0; for(f2 = f1; *f2 && (*f2!=' ') && (*f2!='\t'); f2++){} if(*f2) for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++){} if(strcmp(f1, "exp") == 0){ pw->expire = strtoul(f2, 0, 10); }else if(strcmp(f1, "DISABLED") == 0){ pw->status &= ~Enabled; }else if(strcmp(f1, "STA") == 0){ pw->status |= STA; }else if(strcmp(f1, "failed") == 0){ pw->failed = strtoul(f2, 0, 10); }else if(strcmp(f1, "other") == 0){ pw->other = estrdup(f2); }else if(strcmp(f1, "PAK-Hi") == 0){ pw->Hi = strtomp(f2, nil, 64, nil); } } Bterm(bin); if(dead_or_alive) return pw; /* return PW entry for editing, whether currently valid or not */ if(pw->expire <= now){ werrstr("account expired"); freePW(pw); return nil; } if((pw->status & Enabled) == 0){ werrstr("account disabled"); freePW(pw); return nil; } if(pw->failed < 10) return pw; /* success */ if(now < mtimePW(id)+300){ werrstr("too many failures; try again in five minutes"); freePW(pw); return nil; } pw->failed = 0; putPW(pw); /* reset failed-login-counter after five minutes */ return pw; }