X-Git-Url: http://www.average.org/gitweb/?p=pam_pcsc_cr.git;a=blobdiff_plain;f=authfile.c;h=93157a4e1a9a8460c46a6fc609e1b18a62fd5885;hp=325c29d7a4e66ea96bd79e1efdc47f25b42dc7f1;hb=bcd4173e47de642dd5fa70e1d6019d542ecaf76c;hpb=bcae8a6776e8824e347752d8dc71492adef6aa57 diff --git a/authfile.c b/authfile.c index 325c29d..93157a4 100644 --- a/authfile.c +++ b/authfile.c @@ -34,6 +34,7 @@ freely, subject to the following restrictions: #include #include #include +#include "base64.h" #include "authobj.h" #include "authfile.h" @@ -41,13 +42,11 @@ freely, subject to the following restrictions: * 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. + * substituted with the userid itself. There is no way to make the + * resulting path contain '~'. If there is more than one '~', or if + * the '~' is at the beginning but userid does not resolve via + * getpwnam, or '~' is present but the argument is NULL, path_size + * returns 0, and make_path returns 1. */ static const char *template = "~/.pam_cr/auth"; @@ -57,50 +56,34 @@ void authfile_template(const char *str) template = str; } -static int path_size(const char *tokenid, const char *userid) +/* + I know using these two functions and alloca() in between it ugly, but + I like the alternatives even less. =ec +*/ + +static int path_size(const struct passwd *pw) { - const char *usub; - const char *p, *q; - struct passwd *pw; + const char *p; if ((p = strchr(template, '~')) != strrchr(template, '~')) return 0; - if ((q = strchr(template, '?')) != strrchr(template, '?')) return 0; - if (p && !userid) return 0; - if (q && !tokenid) return 0; - if (p == template) { - pw = getpwnam(userid); - if (!pw) return 0; - usub = pw->pw_dir; - } else { - usub = userid; - } - return strlen(template)+(p?strlen(usub):0)+(q?strlen(tokenid):0)+1; + if (p && !pw) return 0; + if (p == template) return strlen(template)+strlen(pw->pw_dir)+1; + else return strlen(template)+strlen(pw->pw_name)+1; } -static void -make_path(char * const path, const char *tokenid, const char *userid) +static int +make_path(char * const path, const struct passwd *pw) { - const char *usub; const char *p; char *q; - struct passwd *pw; path[0] = '\0'; - if (template[0] == '~') { - pw = getpwnam(userid); - if (!pw) return; - usub = pw->pw_dir; - } else { - usub = userid; - } q = path; for (p = template; *p; p++) switch (*p) { case '~': - strcpy(q, usub); - while (*q) q++; - break; - case '?': - strcpy(q, tokenid); + if (!pw) return 1; + if (p == template) strcpy(q, pw->pw_dir); + else strcpy(q, pw->pw_name); while (*q) q++; break; default: @@ -108,6 +91,7 @@ make_path(char * const path, const char *tokenid, const char *userid) break; } *q = '\0'; + return 0; } int parse(char * const buf, const int argc, const char *argv[const]) @@ -123,8 +107,7 @@ int parse(char * const buf, const int argc, const char *argv[const]) return i != argc; } -struct _auth_obj authfile(const char *tokenid, - const char *userid, const char *password, +struct _auth_obj authfile(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, @@ -132,6 +115,7 @@ struct _auth_obj authfile(const char *tokenid, const int csize)) { struct _auth_obj ret = {0}; + const struct passwd *pw = NULL; mode_t oldmask; FILE *fp = NULL; char *fn, *nfn; @@ -139,23 +123,26 @@ struct _auth_obj authfile(const char *tokenid, struct stat st = {0}; char *buf = NULL; struct { - const char *tokenid; const char *userid; const char *nonce; const char *hablob; - } w = {"", NULL, NULL, NULL}; + } w = {NULL, NULL, NULL}; unsigned char *ablob = NULL; int blobsize = 0; char *newnonce; int nonsize; struct _auth_obj ao; - if ((fnl = path_size(tokenid, userid)) == 0) { - ret.err = "authfile path impossible to build"; + if (userid) pw = getpwnam(userid); + if ((fnl = path_size(pw)) == 0) { + ret.err = "authfile path_size failed"; return ret; } fn = alloca(fnl); - make_path(fn, tokenid, userid); + if (make_path(fn, pw)) { + ret.err = "authfile make_path failed"; + return ret; + } nfn = alloca(fnl+32); snprintf(nfn, fnl+32, "%s.%d.%ld", fn, (int)getpid(), (long)time(NULL)); fp = fopen(fn, "r"); @@ -174,20 +161,10 @@ struct _auth_obj authfile(const char *tokenid, if (ret.err) return ret; if (w.hablob) { - int hlen = strlen(w.hablob); - if (hlen % 32 != 0) { - ret.err = "error: auth string has wrong length"; - } else if (hlen != - strspn(w.hablob, "0123456789abcdefABCDEF")) { - ret.err = "error: auth string not hexadecimal"; - } else { - int i; - - blobsize = hlen/2; - ablob = alloca(blobsize); - for (i = 0; i < blobsize; i++) - sscanf(&w.hablob[i*2], "%2hhx", &ablob[i]); - } + blobsize = strlen(w.hablob)*3/4; + ablob = alloca(blobsize); + if (b64_decode(w.hablob, ablob, &blobsize)) + ret.err = "error: undecodeable auth string"; } if (ret.err) return ret; @@ -213,18 +190,17 @@ struct _auth_obj authfile(const char *tokenid, oldmask = umask(077); if ((fp = fopen(nfn, "w"))) { - int i; + int bsize = ((ao.datasize-1)/3+1)*4+1; + char *b64 = alloca(bsize); - if (fprintf(fp, "%s:%s:%s:", tokenid?tokenid:w.tokenid, - userid?userid:w.userid, newnonce) < 0) { - ret.err = strerror(errno); - } else for (i = 0; i < ao.datasize; i++) - if (fprintf(fp, "%02x", ao.data[i]) < 0) { + if (b64_encode(ao.data, ao.datasize, b64, &bsize)) { + ret.err = "error: could not encode auth string"; + } else if (fprintf(fp, "%s:%s:%s\n", + userid?userid:w.userid, newnonce, b64) < 0) { ret.err = strerror(errno); } - fprintf(fp, "\n"); if (st.st_uid || st.st_gid) { - (void)fchown(fileno(fp), st.st_uid, st.st_gid); + if (fchown(fileno(fp), st.st_uid, st.st_gid)) /*ign*/; } if (fclose(fp) < 0) { ret.err = strerror(errno);