introcude authfile module
authorEugene Crosser <crosser@average.org>
Sun, 10 Nov 2013 13:48:05 +0000 (17:48 +0400)
committerEugene Crosser <crosser@average.org>
Sun, 10 Nov 2013 13:48:05 +0000 (17:48 +0400)
.gitignore
Makefile.am
authfile.c [new file with mode: 0644]
authfile.h [new file with mode: 0644]
pam_cr_setup.c

index d27e9fb1c5af2625d8fd90e849aba30e4a8f5b42..b38c6b7eec4f477a3473eab816b8ca3683d345e8 100644 (file)
@@ -33,3 +33,4 @@ test_serial
 test_serial.trs
 test_auth
 test_auth.trs
+pam_cr_setup
index 2ff0be2321107972599cf37a6eea7f402846ed88..d974a5c104cac542f57c1a394d3c5488138f2653 100644 (file)
@@ -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 (file)
index 0000000..1e0826d
--- /dev/null
@@ -0,0 +1,120 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <alloca.h>
+#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 (file)
index 0000000..2130ce4
--- /dev/null
@@ -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
index d9dfb66acd7c8290d119f908ec48b0a6240c0121..11a8e2ab9bfef0c33f5bf403d73bb8b6758c9e6f 100644 (file)
@@ -6,73 +6,82 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
-#include "authobj.h"
-#if 0
+#include <stdarg.h>
+#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));
 }