--- /dev/null
+#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;
+}
#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;
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) {
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);
}
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));
}