From: Eugene Crosser Date: Tue, 3 Dec 2013 00:06:31 +0000 (+0400) Subject: wip redoing authfile X-Git-Url: http://www.average.org/gitweb/?p=pam_pcsc_cr.git;a=commitdiff_plain;h=33ff3039428415fa441fe9e2b21a854cfcb75151 wip redoing authfile --- diff --git a/authfile.c b/authfile.c index 83477e4..9b1313c 100644 --- a/authfile.c +++ b/authfile.c @@ -3,6 +3,7 @@ #endif #include #include +#include #include #include #include @@ -11,43 +12,97 @@ #include #include "authobj.h" #include "authfile.h" -#include "pcsc_cr.h" -#define OBJSIZE 256 +/* + * Template string may contain zero or one '~' and zero or one '?'. + * '~' at the beginning of the template string is substituted with + * the home directory of the userid. In any other position it is + * substituted with the userid itself. '?' is substituted with the + * tokenid. There is no way to make the resulting path contain '~' + * or '?'. If there is more than one '~' or '?', or if the '~' is + * at the beginning but userid does not resolve via getpwnam, or + * the character to substitute is present but the argument is NULL, + * NULL is returned. Otherwise, malloc()'ed area containg the path + * string. + */ -int update_authfile(const char *fn, const char *tokenid, const char *id, - const char *password, const char *nonce, - const unsigned char *secret, const int secsize, - const unsigned char *payload, const int paysize) +static char *template = "~/.pam_cr/auth"; + +void authfile_template(char *str) +{ + template = str; +} + +static char *make_path(const char *tokenid, const char *userid) +{ + const char *usub; + char *path; + char *p, *q; + struct passwd *pw; + + if ((p = strchr(template, '~')) != strrchr(template, '~')) return NULL; + if ((q = strchr(template, '?')) != strrchr(template, '?')) return NULL; + if (p && !userid) return NULL; + if (q && !tokenid) return NULL; + if (p == template) { + pw = getpwnam(userid); + if (!pw) return NULL; + usub = pw->pw_dir; + } else { + usub = userid; + } + path = malloc(strlen(template) + p?strlen(usub):0 + + q?strlen(tokenid):0 + 1); + if (!path) return NULL; + q = path; + for (p = template; *p; p++) switch (*p) { + case '~': + strcpy(q, usub); + while (*q) q++; + break; + case '?': + strcpy(q, tokenid); + while (*q) q++; + break; + default: + *q++ = *p; + break; + } + *q = '\0'; + return path; +} + +struct _auth_obj authfile(const char *tokenid, + const char *userid, const char *password, + void (*update_nonce)(char *nonce, const int nonsize), + const unsigned char *secret, const int secsize, + const unsigned char *payload, const int paylsize, + struct _auth_chunk (*fetch_key)(const unsigned char *chal, + const int csize)) { - FILE *fp; - int rc; - int i; - unsigned char key[20]; - int keysize = sizeof(key); - unsigned char *mysecret = secret; - int mysecsize = secsize; - unsigned char *myload = payload; - int myloadsize = paysize; - unsigned char *authobj = NULL; - int authsize = 0; + struct _auth_obj ret = {0}; + FILE *fp = NULL; + char *fn; char *buf = NULL; - char *mytokenid = NULL; - char *myid = NULL; - char *mynonce = NULL; - char *hauthobj = NULL; - unsigned char *oldauthobj = NULL; - int oldauthsize; - - if ((fp = fopen(fn, "r"))) { + const char *wtokenid = NULL, *wuserid = NULL, *wnonce = NULL; + const char *hablob = NULL; + unsigned char *ablob = NULL; + int blobsize = 0; + char *newnonce; + int nonsize; + struct _auth_obj ao; + + if ((fn = make_path(tokenid, userid)) == NULL) { + ret.err = "authfile path impossible to build"; + return ret; + } + fp = fopen(fn, "r"); + free(fn); + if (fp) { struct stat st; int fd = fileno(fp); - if (fstat(fd, &st)) { - eprint("fstat \"%s\" (fd %d) error: %s", - fn, fd, strerror(errno)); - st.st_size = 2047; - } + if (fstat(fd, &st)) st.st_size = 2047; if (st.st_size > 2047) st.st_size = 2047; buf = alloca(st.st_size + 1); if (fgets(buf, st.st_size + 1, fp)) { @@ -55,105 +110,97 @@ int update_authfile(const char *fn, const char *tokenid, const char *id, p = &buf[strlen(buf) - 1]; while (*p == '\n' || *p == '\r') *p-- = '\0'; - mytokenid = strtok(buf, ":"); - myid = strtok(NULL, ":"); - mynonce = strtok(NULL, ":"); - hauthobj = strtok(NULL, ":"); + wtokenid = strtok(buf, ":"); + wuserid = strtok(NULL, ":"); + wnonce = strtok(NULL, ":"); + hablob = strtok(NULL, ":"); } else { - eprint("error reading from %s: %s", - fn, strerror(errno)); + ret.err = strerror(errno); } fclose(fp); } - if (hauthobj) { - int hlen; + if (ret.err) return ret; - hlen = strlen(hauthobj); + if (hablob) { + int hlen = strlen(hablob); if (hlen % 32 != 0) { - eprint("error: auth string has wrong length"); + ret.err = "error: auth string has wrong length"; } else if (hlen != - strspn(hauthobj, "0123456789abcdefABCDEF")) { - eprint("error: auth string not hexadecimal"); + strspn(hablob, "0123456789abcdefABCDEF")) { + ret.err = "error: auth string not hexadecimal"; } else { - oldauthsize = hlen/2; - oldauthobj = alloca(oldauthsize); - for (i = 0; i < oldauthsize; i++) - sscanf(&hauthobj[i*2], "%2hhx", &oldauthobj[i]); + int i; + + blobsize = hlen/2; + ablob = alloca(blobsize); + for (i = 0; i < blobsize; i++) + sscanf(&hablob[i*2], "%2hhx", &ablob[i]); } } + if (ret.err) return ret; - if (!secret) { - unsigned char chal[64]; - int csize = sizeof(chal); - long rc; + nonsize = wnonce ? strlen(wnonce)*2 : 32; + if (nonsize < 32) nonsize = 32; + newnonce = alloca(nonsize); + if (wnonce) strcpy(newnonce, wnonce); + else memset(newnonce, 0, nonsize); + update_nonce(newnonce, nonsize); - if (!oldauthobj || !password) { - eprint("if no secret given, old auth file must" - " be present and password must be given"); - return -1; - } - rc = make_challenge(myid, password, mynonce, chal, &csize); - if (rc) { - eprint("cannot make challenge"); - return -1; - } - rc = pcsc_cr(chal, csize, key, &keysize); - if (rc) { - eprint("error querying token: %s", pcsc_errstr(rc)); - return -1; - } - mysecsize = oldauthsize; - mysecret = alloca(mysecsize); - myloadsize = oldauthsize; - myload = alloca(myloadsize); - rc = parse_authobj(key, keysize, oldauthobj, oldauthsize, - mysecret, &mysecsize, myload, &myloadsize); - if (rc) { - eprint("cannot parse old authobj: %d", rc); - return -1; - } - } - if (tokenid) mytokenid = tokenid; - if (id) myid = id; - if (nonce) mynonce = nonce; - else { - unsigned int prev = atoi(mynonce); - mynonce = alloca(16); - sprintf(mynonce, "%d", prev + 1); - } + ao = authobj(userid?userid:wuserid, password, + wnonce, newnonce, secret, secsize, + payload, paylsize, ablob, blobsize, + fetch_key); - authsize = ((mysecsize + myloadsize + 16 + 4 * sizeof(short) - 1) / - 16 + 1) * 16; - authobj = alloca(authsize); - rc = make_authobj(myid, password, mynonce, mysecret, mysecsize, - myload, myloadsize, authobj, &authsize); - if (rc) { - eprint("make_authobj error %d", rc); - return -1; + if (ao.err) { + ret.err = ao.err; + if (ao.data) memset(ao.data, 0, ao.datasize); + if (ao.payload) memset(ao.payload, 0, ao.paylsize); + if (ao.buffer) free(ao.buffer); + return ret; } if ((fp = fopen(fn, "w"))) { - if (fprintf(fp, "%s:%s:%s:", mytokenid, myid, mynonce) < 0) { - eprint("cannot write to \"%s\": %s", - fn, strerror(errno)); - return -1; - } - for (i = 0; i < authsize; i++) - if (fprintf(fp, "%02x", authobj[i]) < 0) { - eprint("cannot write to \"%s\": %s", - fn, strerror(errno)); - return -1; + int i; + + if (fprintf(fp, "%s:%s:%s:", tokenid?tokenid:wtokenid, + userid?userid:wuserid, newnonce) < 0) { + ret.err = strerror(errno); + } else for (i = 0; i < ao.datasize; i++) + if (fprintf(fp, "%02x", ao.data[i]) < 0) { + ret.err = strerror(errno); } fprintf(fp, "\n"); if (fclose(fp) < 0) { - eprint("cannot close \"%s\": %s", - fn, strerror(errno)); - return -1; + ret.err = strerror(errno); } } else { - eprint("cannot open \"%s\": %s", - fn, strerror(errno)); - return -1; + ret.err = strerror(errno); + } + + if (!ret.err) { + int bufsize = (wuserid?strlen(wuserid)+1:0) + ao.paylsize; + if (bufsize) { + if ((ret.buffer = malloc(bufsize)) == NULL) { + ret.err = "authfile malloc failed"; + } else { + unsigned char *p = ret.buffer; + if (wuserid) { + strcpy((char*)p, wuserid); + ret.data = p; + ret.datasize = strlen(wuserid)+1; + p += strlen(wuserid)+1; + } + if (ao.payload) { + memcpy(p, ao.payload, ao.paylsize); + ret.payload = p; + ret.paylsize = ao.paylsize; + } + } + } } - return 0; + + if (ao.data) memset(ao.data, 0, ao.datasize); + if (ao.payload) memset(ao.payload, 0, ao.paylsize); + if (ao.buffer) free(ao.buffer); + return ret; } diff --git a/authfile.h b/authfile.h index 2130ce4..4a12aaa 100644 --- a/authfile.h +++ b/authfile.h @@ -1,11 +1,14 @@ #ifndef _AUTHFILE_H #define _AUTHFILE_H -int eprint(const char *format, ...); /* must be provided by the caller */ +void authfile_template(char *template); -int update_authfile(const char *fn, const char *tokenid, const char *id, - const char *password, const char *nonce, +struct _auth_obj authfile(const char *tokenid, + const char *userid, const char *password, + void (*update_nonce)(char *nonce, const int nonsize), const unsigned char *secret, const int secsize, - const unsigned char *payload, const int paysize); + const unsigned char *payload, const int paysize, + struct _auth_chunk (*fetch_key)(const unsigned char *chal, + const int csize)); #endif