From 4a5da38dfd8b0236564ffe6b70eab1eeb399fff0 Mon Sep 17 00:00:00 2001 From: Eugene Crosser Date: Sun, 10 Nov 2013 17:48:05 +0400 Subject: [PATCH] introcude authfile module --- .gitignore | 1 + Makefile.am | 6 ++- authfile.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ authfile.h | 11 +++++ pam_cr_setup.c | 129 +++++++++++++++++++++---------------------------- 5 files changed, 192 insertions(+), 75 deletions(-) create mode 100644 authfile.c create mode 100644 authfile.h diff --git a/.gitignore b/.gitignore index d27e9fb..b38c6b7 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ test_serial test_serial.trs test_auth test_auth.trs +pam_cr_setup diff --git a/Makefile.am b/Makefile.am index 2ff0be2..d974a5c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,10 +3,12 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -noinst_HEADERS = pcsc_cr.h token.h crypto_if.h crypto.h serial.h authobj.h +noinst_HEADERS = pcsc_cr.h token.h crypto_if.h crypto.h serial.h authobj.h \ + authfile.h EXTRA_LTLIBRARIES = libpcsc_cr.la -libpcsc_cr_la_SOURCES = authobj.c serial.c crypto.c pcsc_cr.c ykneo.c +libpcsc_cr_la_SOURCES = authfile.c authobj.c serial.c crypto.c pcsc_cr.c \ + ykneo.c EXTRA_libpcsc_cr_la_SOURCES = ossl_crypto.c tom_crypto.c gnu_crypto.c libpcsc_cr_la_LIBADD = @CRYPTO_OBJS@ libpcsc_cr_la_DEPENDENCIES = @CRYPTO_OBJS@ diff --git a/authfile.c b/authfile.c new file mode 100644 index 0000000..1e0826d --- /dev/null +++ b/authfile.c @@ -0,0 +1,120 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "authobj.h" +#include "authfile.h" +#include "pcsc_cr.h" + +#define OBJSIZE 256 + +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) +{ + FILE *fp; + int rc; + int i; + unsigned char key[20]; + int keysize = sizeof(key); + unsigned char mysecret[20]; + int mysecsize = sizeof(mysecret); + unsigned char myload[256]; + int myloadsize = sizeof(myload); + unsigned char *authobj = alloca(OBJSIZE); + int authsize = OBJSIZE; + char buf[512]; + char *oldtokenid = NULL, *oldid = NULL, *oldnonce = NULL, + *hauthobj = NULL; + unsigned char *oldauthobj = NULL; + int oldauthsize; + + if ((fp = fopen(fn, "r"))) { + if (fgets(buf, sizeof(buf), fp)) { + oldtokenid = strtok(buf, ":\r\n"); + oldid = strtok(NULL, ":\r\n"); + oldnonce = strtok(NULL, ":\r\n"); + hauthobj = strtok(NULL, ":\r\n"); + } else { + eprint("error reading from %s: %s\n", + fn, strerror(errno)); + } + fclose(fp); + } + if (hauthobj) { + int hlen; + + hlen = strlen(hauthobj); + if (hlen % 32 != 0) { + eprint("error: auth string has wrong length\n"); + } else if (hlen != + strspn(hauthobj, "0123456789abcdefABCDEF")) { + eprint("error: auth string not hexadecimal\n"); + } else { + oldauthsize = hlen/2; + oldauthobj = alloca(oldauthsize); + for (i = 0; i < oldauthsize; i++) + sscanf(&hauthobj[i*2], "%2hhx", &oldauthobj[i]); + } + } + + if (oldauthobj && password && !secret) { + unsigned char chal[64]; + int csize = sizeof(chal); + long rc; + + rc = make_challenge(id, password, nonce, chal, &csize); + if (rc) { + eprint("cannot make challenge\n"); + return -1; + } + rc = pcsc_cr(chal, csize, key, &keysize); + if (rc) { + eprint("error querying token: %s\n", pcsc_errstr(rc)); + return -1; + } + rc = parse_authobj(key, keysize, oldauthobj, oldauthsize, + mysecret, &mysecsize, myload, &myloadsize); + if (rc) { + eprint("cannot parse old authobj: %d\n", rc); + return -1; + } + } + + rc = make_authobj(id, password, nonce, mysecret, mysecsize, + payload, paysize, authobj, &authsize); + if (rc) { + eprint("make_authobj error %d\n", rc); + return -1; + } + fp = fopen(fn, "w"); + if (!fp) { + eprint("cannot open \"%s\": %s\n", + fn, strerror(errno)); + return -1; + } + if (fprintf(fp, "%s:%s:%s:", tokenid, id, nonce) < 0) { + eprint("cannot write to \"%s\": %s\n", + fn, strerror(errno)); + return -1; + } + for (i = 0; i < authsize; i++) + if (fprintf(fp, "%02x", authobj[i]) < 0) { + eprint("cannot write to \"%s\": %s\n", + fn, strerror(errno)); + return -1; + } + fprintf(fp, "\n"); + if (fclose(fp) < 0) { + eprint("cannot close \"%s\": %s\n", + fn, strerror(errno)); + return -1; + } + return 0; +} diff --git a/authfile.h b/authfile.h new file mode 100644 index 0000000..2130ce4 --- /dev/null +++ b/authfile.h @@ -0,0 +1,11 @@ +#ifndef _AUTHFILE_H +#define _AUTHFILE_H + +int eprint(const char *format, ...); /* must be provided by the caller */ + +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); + +#endif diff --git a/pam_cr_setup.c b/pam_cr_setup.c index d9dfb66..11a8e2a 100644 --- a/pam_cr_setup.c +++ b/pam_cr_setup.c @@ -6,73 +6,82 @@ #include #include #include -#include "authobj.h" -#if 0 +#include +#include "authfile.h" #include "pcsc_cr.h" -#endif + +int eprint(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + return vfprintf(stderr, format, ap); + va_end(ap); +} static void usage(const char const *cmd) { - fprintf(stderr, - "usage: %s [-f filename] {-s hexstring40 | -S file} [-u username] [-n nonce] [-l payload] [-p password]\n", - cmd); + eprint( "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" + " -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\n" + , cmd); } int main(int argc, char *argv[]) { int c; char *fn = NULL; - FILE *fp; char *hsecret = NULL; char *secfn = NULL; char secbuf[43]; - unsigned char secret[20]; + unsigned char bsecret[20]; + unsigned char *secret = NULL; int i; char *nonce = "1"; + char *tokenid = ""; char *id = getlogin(); char *payload = ""; char *password = ""; - int rc; - unsigned char authobj[256]; - int authsize = sizeof(authobj); - while ((c = getopt(argc, argv, "h" -#if 0 - "o:" -#endif - "f:s:S:u:n:l:p:")) != -1) switch (c) { + while ((c = getopt(argc, argv, "ho:f:a:A:s:n:l:p:")) != -1) + switch (c) { case 'h': usage(argv[0]); exit(EXIT_SUCCESS); -#if 0 case 'o': if (pcsc_option(optarg)) { - fprintf(stderr, "Option \"%s\" bad\n", optarg); + eprint("Option \"%s\" bad\n", optarg); exit(EXIT_FAILURE); } break; -#endif case 'f': fn = optarg; break; - case 's': + case 'a': if (!secfn) { hsecret = optarg; } else { - fprintf(stderr, "-s and -S are mutually exclusive\n"); + eprint("-a and -A are mutually exclusive\n"); exit(EXIT_FAILURE); } break; - case 'S': + case 'A': if (!hsecret) { secfn = optarg; } else { - fprintf(stderr, "-S and -s are mutually exclusive\n"); + eprint("-A and -a are mutually exclusive\n"); exit(EXIT_FAILURE); } break; - case 'u': - id = optarg; + case 's': + tokenid = optarg; break; case 'n': nonce = optarg; @@ -87,8 +96,8 @@ int main(int argc, char *argv[]) usage(argv[0]); exit(EXIT_FAILURE); } - if (optind == (argc - 1) && !secfn && !hsecret) { - hsecret = argv[optind]; + if (optind == (argc - 1)) { + id = argv[optind]; optind++; } if (optind != argc) { @@ -102,12 +111,12 @@ int main(int argc, char *argv[]) if (!strcmp(secfn, "-")) sfp = stdin; else sfp = fopen(secfn, "r"); if (!sfp) { - fprintf(stderr, "cannot open \"%s\": %s\n", + eprint("cannot open \"%s\": %s\n", secfn, strerror(errno)); exit(EXIT_FAILURE); } if (!fgets(secbuf, sizeof(secbuf), sfp)) { - fprintf(stderr, "cannot read \"%s\": %s\n", + eprint("cannot read \"%s\": %s\n", secfn, strerror(errno)); exit(EXIT_FAILURE); } @@ -117,52 +126,26 @@ int main(int argc, char *argv[]) fclose(sfp); hsecret = secbuf; } - if (!hsecret) { - fprintf(stderr, "secret missing, specify -s or -S\n"); - exit(EXIT_FAILURE); - } - if (strlen(hsecret) != 40) { - fprintf(stderr, "secret wrong, must be exactly 40 chars\n"); - exit(EXIT_FAILURE); - } - for (i = 0; i < 20; i++) - if (sscanf(hsecret + i * 2, "%2hhx", &secret[i]) != 1) { - fprintf(stderr, "secret wrong, must be hexadecimal\n"); - exit(EXIT_FAILURE); - } if (!id) { - fprintf(stderr, "cannot determine userid\n"); - exit(EXIT_FAILURE); - } - rc = make_authobj(id, password, nonce, secret, sizeof(secret), - (unsigned char *)payload, strlen(payload), - authobj, &authsize); - if (rc) { - fprintf(stderr, "error %d\n", rc); - exit(EXIT_FAILURE); - } - fp = fopen(fn, "w"); - if (!fp) { - fprintf(stderr, "cannot open \"%s\": %s\n", - fn, strerror(errno)); - exit(EXIT_FAILURE); - } - if (fprintf(fp, "%s:%s:%s:", "", id, nonce) < 0) { - fprintf(stderr, "cannot write to \"%s\": %s\n", - fn, strerror(errno)); + eprint("cannot determine userid\n"); exit(EXIT_FAILURE); } - for (i = 0; i < authsize; i++) - if (fprintf(fp, "%02x", authobj[i]) < 0) { - fprintf(stderr, "cannot write to \"%s\": %s\n", - fn, strerror(errno)); - exit(EXIT_FAILURE); - } - fprintf(fp, "\n"); - if (fclose(fp) < 0) { - fprintf(stderr, "cannot close \"%s\": %s\n", - fn, strerror(errno)); - exit(EXIT_FAILURE); + if (hsecret) { + if (strlen(hsecret) != 40) { + fprintf(stderr, + "secret wrong, must be exactly 40 chars\n"); + exit(EXIT_FAILURE); + } + if (strspn(hsecret, "0123456789abcdefABCDEF") != 40) { + fprintf(stderr, + "secret wrong, must be hexadecimal string\n"); + exit(EXIT_FAILURE); + } + for (i = 0; i < 20; i++) + sscanf(hsecret + i * 2, "%2hhx", &bsecret[i]); + secret = bsecret; } - return 0; + return update_authfile(fn, tokenid, id, password, nonce, + secret, sizeof(bsecret), + (unsigned char *)payload, strlen(payload)); } -- 2.39.2