8b077df0a0c74e2bb800b6f6883fba18acdaa7da
[pam_pcsc_cr.git] / authfile.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <alloca.h>
10 #include "authobj.h"
11 #include "authfile.h"
12 #include "pcsc_cr.h"
13
14 #define OBJSIZE 256
15
16 int update_authfile(const char *fn, const char *tokenid, const char *id,
17                 const char *password, const char *nonce,
18                 const unsigned char *secret, const int secsize,
19                 const unsigned char *payload, const int paysize)
20 {
21         FILE *fp;
22         int rc;
23         int i;
24         unsigned char key[20];
25         int keysize = sizeof(key);
26         unsigned char mysecret[20];
27         int mysecsize = sizeof(mysecret);
28         unsigned char myload[256];
29         int myloadsize = sizeof(myload);
30         unsigned char *authobj = alloca(OBJSIZE);
31         int authsize = OBJSIZE;
32         char buf[512];
33         char *oldtokenid = NULL, *oldid = NULL, *oldnonce = NULL,
34                 *hauthobj = NULL;
35         unsigned char *oldauthobj = NULL;
36         int oldauthsize;
37
38         if ((fp = fopen(fn, "r"))) {
39                 if (fgets(buf, sizeof(buf), fp)) {
40                         oldtokenid = strtok(buf, ":\r\n");
41                         oldid = strtok(NULL, ":\r\n");
42                         oldnonce = strtok(NULL, ":\r\n");
43                         hauthobj = strtok(NULL, ":\r\n");
44                 } else {
45                         eprint("error reading from %s: %s",
46                                 fn, strerror(errno));
47                 }
48                 fclose(fp);
49         }
50         if (hauthobj) {
51                 int hlen;
52
53                 hlen = strlen(hauthobj);
54                 if (hlen % 32 != 0) {
55                         eprint("error: auth string has wrong length");
56                 } else if (hlen !=
57                                 strspn(hauthobj, "0123456789abcdefABCDEF")) {
58                         eprint("error: auth string not hexadecimal");
59                 } else {
60                         oldauthsize = hlen/2;
61                         oldauthobj = alloca(oldauthsize);
62                         for (i = 0; i < oldauthsize; i++)
63                                 sscanf(&hauthobj[i*2], "%2hhx", &oldauthobj[i]);
64                 }
65         }
66
67         if (oldauthobj && password && !secret) {
68                 unsigned char chal[64];
69                 int csize = sizeof(chal);
70                 long rc;
71
72                 rc = make_challenge(id, password, nonce, chal, &csize);
73                 if (rc) {
74                         eprint("cannot make challenge");
75                         return -1;
76                 }
77                 rc = pcsc_cr(chal, csize, key, &keysize);
78                 if (rc) {
79                         eprint("error querying token: %s", pcsc_errstr(rc));
80                         return -1;
81                 }
82                 rc = parse_authobj(key, keysize, oldauthobj, oldauthsize,
83                         mysecret, &mysecsize, myload, &myloadsize);
84                 if (rc) {
85                         eprint("cannot parse old authobj: %d", rc);
86                         return -1;
87                 }
88         }
89
90         rc = make_authobj(id, password, nonce, mysecret, mysecsize,
91                         payload, paysize, authobj, &authsize);
92         if (rc) {
93                 eprint("make_authobj error %d", rc);
94                 return -1;
95         }
96         fp = fopen(fn, "w");
97         if (!fp) {
98                 eprint("cannot open \"%s\": %s",
99                         fn, strerror(errno));
100                 return -1;
101         }
102         if (fprintf(fp, "%s:%s:%s:", tokenid, id, nonce) < 0) {
103                 eprint("cannot write to \"%s\": %s",
104                         fn, strerror(errno));
105                 return -1;
106         }
107         for (i = 0; i < authsize; i++)
108             if (fprintf(fp, "%02x", authobj[i]) < 0) {
109                 eprint("cannot write to \"%s\": %s",
110                         fn, strerror(errno));
111                 return -1;
112         }
113         fprintf(fp, "\n");
114         if (fclose(fp) < 0) {
115                 eprint("cannot close \"%s\": %s",
116                         fn, strerror(errno));
117                 return -1;
118         }
119         return 0;
120 }