From: Eugene Crosser Date: Tue, 3 Dec 2013 22:12:23 +0000 (+0400) Subject: authfile works (except strtok) X-Git-Url: http://www.average.org/gitweb/?p=pam_pcsc_cr.git;a=commitdiff_plain;h=30e8d5368d77e5879e3f6760db4d9d5bc38497bc authfile works (except strtok) --- diff --git a/authfile.c b/authfile.c index 9b1313c..f7daa60 100644 --- a/authfile.c +++ b/authfile.c @@ -33,27 +33,41 @@ void authfile_template(char *str) template = str; } -static char *make_path(const char *tokenid, const char *userid) +static int path_size(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 = 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 NULL; + if (!pw) return 0; + usub = pw->pw_dir; + } else { + usub = userid; + } + return strlen(template) + p?strlen(usub):0 + q?strlen(tokenid):0 + 1; +} + +static void +make_path(char * const path, const char *tokenid, const char *userid) +{ + const char *usub; + char *p, *q; + struct passwd *pw; + + path[0] = '\0'; + if (template[0] == '~') { + pw = getpwnam(userid); + if (!pw) return; 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 '~': @@ -69,7 +83,6 @@ static char *make_path(const char *tokenid, const char *userid) break; } *q = '\0'; - return path; } struct _auth_obj authfile(const char *tokenid, @@ -81,10 +94,12 @@ struct _auth_obj authfile(const char *tokenid, const int csize)) { struct _auth_obj ret = {0}; + mode_t oldmask; FILE *fp = NULL; char *fn; + int fnl; char *buf = NULL; - const char *wtokenid = NULL, *wuserid = NULL, *wnonce = NULL; + const char *wtokenid = "", *wuserid = NULL, *wnonce = NULL; const char *hablob = NULL; unsigned char *ablob = NULL; int blobsize = 0; @@ -92,12 +107,13 @@ struct _auth_obj authfile(const char *tokenid, int nonsize; struct _auth_obj ao; - if ((fn = make_path(tokenid, userid)) == NULL) { + if ((fnl = path_size(tokenid, userid)) == 0) { ret.err = "authfile path impossible to build"; return ret; } + fn = alloca(fnl); + make_path(fn, tokenid, userid); fp = fopen(fn, "r"); - free(fn); if (fp) { struct stat st; int fd = fileno(fp); @@ -159,6 +175,7 @@ struct _auth_obj authfile(const char *tokenid, return ret; } + oldmask = umask(077); if ((fp = fopen(fn, "w"))) { int i; @@ -176,6 +193,7 @@ struct _auth_obj authfile(const char *tokenid, } else { ret.err = strerror(errno); } + (void)umask(oldmask); if (!ret.err) { int bufsize = (wuserid?strlen(wuserid)+1:0) + ao.paylsize; diff --git a/pam_cr_setup.c b/pam_cr_setup.c index e0fb52a..8a42a74 100644 --- a/pam_cr_setup.c +++ b/pam_cr_setup.c @@ -7,72 +7,89 @@ #include #include #include +#include "authobj.h" #include "authfile.h" #include "pcsc_cr.h" -int eprint(const char *format, ...) +static struct _auth_chunk +token_key(const unsigned char *challenge, const int challengesize) { - va_list ap; - char *nfmt; + struct _auth_chunk ho = {0}; + long rc; + int keysize = sizeof(ho.data); - nfmt = alloca(strlen(format)+2); - strcpy(nfmt, format); - strcat(nfmt, "\n"); - va_start(ap, format); - return vfprintf(stderr, nfmt, ap); - va_end(ap); + if ((rc = pcsc_cr(challenge, challengesize, ho.data, &keysize))) { + ho.err = pcsc_errstr(rc); + } + return ho; +} + +static char *mynonce = NULL; + +static void update_nonce(char *nonce, const int nonsize) +{ + if (mynonce) { + snprintf(nonce, nonsize, "%s", mynonce); + } else { + int n = 0; + + sscanf(nonce, "%d", &n); + snprintf(nonce, nonsize, "%d", n+1); + } } -static void usage(const char const *cmd) +static void usage(const char * const cmd) { - eprint( "usage: %s [options] [username]\n" + fprintf(stderr, + "usage: %s [options] [username]\n" " -h - show this help and exit\n" " -o backend-option - token option \"backend:key=val\"\n" - " -f auth-file - auth state file to read/write\n" + " -f template - template for auth state filepath\n" " -a secret | -A file-with-secret | -A -\n" " - 40-character hexadecimal secret\n" " -s token-serial - public I.D. of the token\n" " -n nonce - initial nonce\n" " -l payload - keyring unlock password\n" - " -p password - login password" + " -p password - login password\n" + " -v - show returned data\n" , cmd); } int main(int argc, char *argv[]) { + struct _auth_obj ao; int c; - char *fn = NULL; + int verbose = 0; char *hsecret = NULL; char *secfn = NULL; char secbuf[43]; unsigned char bsecret[20]; unsigned char *secret = NULL; int i; - char *nonce = NULL; char *tokenid = NULL; - char *id = getlogin(); - char *payload = ""; + char *userid = getlogin(); + char *payload = NULL; char *password = ""; - while ((c = getopt(argc, argv, "ho:f:a:A:s:n:l:p:")) != -1) + while ((c = getopt(argc, argv, "ho:f:a:A:s:n:l:p:v")) != -1) switch (c) { case 'h': usage(argv[0]); exit(EXIT_SUCCESS); case 'o': if (pcsc_option(optarg)) { - eprint("Option \"%s\" bad", optarg); + fprintf(stderr, "Option \"%s\" bad", optarg); exit(EXIT_FAILURE); } break; case 'f': - fn = optarg; + authfile_template(optarg); break; case 'a': if (!secfn) { hsecret = optarg; } else { - eprint("-a and -A are mutually exclusive"); + fprintf(stderr, "-a and -A are mutually exclusive"); exit(EXIT_FAILURE); } break; @@ -80,7 +97,7 @@ int main(int argc, char *argv[]) if (!hsecret) { secfn = optarg; } else { - eprint("-A and -a are mutually exclusive"); + fprintf(stderr, "-A and -a are mutually exclusive"); exit(EXIT_FAILURE); } break; @@ -88,7 +105,7 @@ int main(int argc, char *argv[]) tokenid = optarg; break; case 'n': - nonce = optarg; + mynonce = optarg; break; case 'l': payload = optarg; @@ -96,18 +113,25 @@ int main(int argc, char *argv[]) case 'p': password = optarg; break; + case 'v': + verbose = 1; + break; default: usage(argv[0]); exit(EXIT_FAILURE); } if (optind == (argc - 1)) { - id = argv[optind]; + userid = argv[optind]; optind++; } if (optind != argc) { usage(argv[0]); exit(EXIT_FAILURE); } + if (!userid) { + fprintf(stderr, "cannot determine userid"); + exit(EXIT_FAILURE); + } if (secfn) { FILE *sfp; char *p; @@ -115,12 +139,12 @@ int main(int argc, char *argv[]) if (!strcmp(secfn, "-")) sfp = stdin; else sfp = fopen(secfn, "r"); if (!sfp) { - eprint("cannot open \"%s\": %s", + fprintf(stderr, "cannot open \"%s\": %s", secfn, strerror(errno)); exit(EXIT_FAILURE); } if (!fgets(secbuf, sizeof(secbuf), sfp)) { - eprint("cannot read \"%s\": %s", + fprintf(stderr, "cannot read \"%s\": %s", secfn, strerror(errno)); exit(EXIT_FAILURE); } @@ -130,10 +154,6 @@ int main(int argc, char *argv[]) fclose(sfp); hsecret = secbuf; } - if (!id) { - eprint("cannot determine userid"); - exit(EXIT_FAILURE); - } if (hsecret) { if (strlen(hsecret) != 40) { fprintf(stderr, @@ -149,7 +169,18 @@ int main(int argc, char *argv[]) sscanf(hsecret + i * 2, "%2hhx", &bsecret[i]); secret = bsecret; } - return update_authfile(fn, tokenid, id, password, nonce, - secret, sizeof(bsecret), - (unsigned char *)payload, strlen(payload)); + ao = authfile(tokenid, userid, password, update_nonce, + secret, secret ? sizeof(bsecret) : 0, + (unsigned char *)payload, payload ? strlen(payload) : 0, + token_key); + memset(bsecret, 0, sizeof(bsecret)); + if (ao.err) { + fprintf(stderr, "%s\n", ao.err); + exit(EXIT_FAILURE); + } else if (verbose) { + printf("userid : \"%.*s\"\n", ao.datasize, ao.data); + printf("payload: \"%.*s\"\n", ao.paylsize, ao.payload); + } + if (ao.buffer) free(ao.buffer); + return 0; }