8a42a74e3886c5128b3a925e795933d75da93a6a
[pam_pcsc_cr.git] / pam_cr_setup.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 <stdarg.h>
10 #include "authobj.h"
11 #include "authfile.h"
12 #include "pcsc_cr.h"
13
14 static struct _auth_chunk
15 token_key(const unsigned char *challenge, const int challengesize)
16 {
17         struct _auth_chunk ho = {0};
18         long rc;
19         int keysize = sizeof(ho.data);
20
21         if ((rc = pcsc_cr(challenge, challengesize, ho.data, &keysize))) {
22                 ho.err = pcsc_errstr(rc);
23         }
24         return ho;
25 }
26
27 static char *mynonce = NULL;
28
29 static void update_nonce(char *nonce, const int nonsize)
30 {
31         if (mynonce) {
32                 snprintf(nonce, nonsize, "%s", mynonce);
33         } else {
34                 int n = 0;
35
36                 sscanf(nonce, "%d", &n);
37                 snprintf(nonce, nonsize, "%d", n+1);
38         }
39 }
40
41 static void usage(const char * const cmd)
42 {
43         fprintf(stderr,
44                 "usage: %s [options] [username]\n"
45                 "    -h                - show this help and exit\n"
46                 "    -o backend-option - token option \"backend:key=val\"\n"
47                 "    -f template       - template for auth state filepath\n"
48                 "    -a secret | -A file-with-secret | -A -\n"
49                 "                      - 40-character hexadecimal secret\n"
50                 "    -s token-serial   - public I.D. of the token\n"
51                 "    -n nonce          - initial nonce\n"
52                 "    -l payload        - keyring unlock password\n"
53                 "    -p password       - login password\n"
54                 "    -v                - show returned data\n"
55                 , cmd);
56 }
57
58 int main(int argc, char *argv[])
59 {
60         struct _auth_obj ao;
61         int c;
62         int verbose = 0;
63         char *hsecret = NULL;
64         char *secfn = NULL;
65         char secbuf[43];
66         unsigned char bsecret[20];
67         unsigned char *secret = NULL;
68         int i;
69         char *tokenid = NULL;
70         char *userid = getlogin();
71         char *payload = NULL;
72         char *password = "";
73
74         while ((c = getopt(argc, argv, "ho:f:a:A:s:n:l:p:v")) != -1)
75             switch (c) {
76         case 'h':
77                 usage(argv[0]);
78                 exit(EXIT_SUCCESS);
79         case 'o':
80                 if (pcsc_option(optarg)) {
81                         fprintf(stderr, "Option \"%s\" bad", optarg);
82                         exit(EXIT_FAILURE);
83                 }
84                 break;
85         case 'f':
86                 authfile_template(optarg);
87                 break;
88         case 'a':
89                 if (!secfn) {
90                         hsecret = optarg;
91                 } else {
92                         fprintf(stderr, "-a and -A are mutually exclusive");
93                         exit(EXIT_FAILURE);
94                 }
95                 break;
96         case 'A':
97                 if (!hsecret) {
98                         secfn = optarg;
99                 } else {
100                         fprintf(stderr, "-A and -a are mutually exclusive");
101                         exit(EXIT_FAILURE);
102                 }
103                 break;
104         case 's':
105                 tokenid = optarg;
106                 break;
107         case 'n':
108                 mynonce = optarg;
109                 break;
110         case 'l':
111                 payload = optarg;
112                 break;
113         case 'p':
114                 password = optarg;
115                 break;
116         case 'v':
117                 verbose = 1;
118                 break;
119         default:
120                 usage(argv[0]);
121                 exit(EXIT_FAILURE);
122         }
123         if (optind == (argc - 1)) {
124                 userid = argv[optind];
125                 optind++;
126         }
127         if (optind != argc) {
128                 usage(argv[0]);
129                 exit(EXIT_FAILURE);
130         }
131         if (!userid) {
132                 fprintf(stderr, "cannot determine userid");
133                 exit(EXIT_FAILURE);
134         }
135         if (secfn) {
136                 FILE *sfp;
137                 char *p;
138
139                 if (!strcmp(secfn, "-")) sfp = stdin;
140                 else sfp = fopen(secfn, "r");
141                 if (!sfp) {
142                         fprintf(stderr, "cannot open \"%s\": %s",
143                                 secfn, strerror(errno));
144                         exit(EXIT_FAILURE);
145                 }
146                 if (!fgets(secbuf, sizeof(secbuf), sfp)) {
147                         fprintf(stderr, "cannot read \"%s\": %s",
148                                 secfn, strerror(errno));
149                         exit(EXIT_FAILURE);
150                 }
151                 for (p = secbuf + strlen(secbuf) - 1;
152                         *p == '\n' || *p == '\r'; p--) *p = '\n';
153
154                 fclose(sfp);
155                 hsecret = secbuf;
156         }
157         if (hsecret) {
158                 if (strlen(hsecret) != 40) {
159                         fprintf(stderr,
160                                 "secret wrong, must be exactly 40 chars\n");
161                         exit(EXIT_FAILURE);
162                 }
163                 if (strspn(hsecret, "0123456789abcdefABCDEF") != 40) {
164                         fprintf(stderr,
165                                 "secret wrong, must be hexadecimal string\n");
166                         exit(EXIT_FAILURE);
167                 }
168                 for (i = 0; i < 20; i++)
169                         sscanf(hsecret + i * 2, "%2hhx", &bsecret[i]);
170                 secret = bsecret;
171         }
172         ao = authfile(tokenid, userid, password, update_nonce,
173                         secret, secret ? sizeof(bsecret) : 0,
174                         (unsigned char *)payload, payload ? strlen(payload) : 0,
175                         token_key);
176         memset(bsecret, 0, sizeof(bsecret));
177         if (ao.err) {
178                 fprintf(stderr, "%s\n", ao.err);
179                 exit(EXIT_FAILURE);
180         } else if (verbose) {
181                 printf("userid : \"%.*s\"\n", ao.datasize, ao.data);
182                 printf("payload: \"%.*s\"\n", ao.paylsize, ao.payload);
183         }
184         if (ao.buffer) free(ao.buffer);
185         return 0;
186 }