]> www.average.org Git - pam_pcsc_cr.git/blobdiff - authfile.c
.su objects to gitignore
[pam_pcsc_cr.git] / authfile.c
index 2d30ed83b1ed708736e3d4a4f66a350e35aee8dd..93157a4e1a9a8460c46a6fc609e1b18a62fd5885 100644 (file)
@@ -34,6 +34,7 @@ freely, subject to the following restrictions:
 #include <unistd.h>
 #include <errno.h>
 #include <alloca.h>
+#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,37 +115,39 @@ 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;
        int fnl;
+       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");
        if (fp) {
-               struct stat st;
-               int fd = fileno(fp);
-
-               if (fstat(fd, &st)) st.st_size = 2047;
+               if (fstat(fileno(fp), &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)) {
@@ -176,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;
 
@@ -215,16 +190,18 @@ 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) {
+                       if (fchown(fileno(fp), st.st_uid, st.st_gid)) /*ign*/;
+               }
                if (fclose(fp) < 0) {
                        ret.err = strerror(errno);
                }