e0fb52a61d992cffa912cde3de482d39d7431902
[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 "authfile.h"
11 #include "pcsc_cr.h"
12
13 int eprint(const char *format, ...)
14 {
15         va_list ap;
16         char *nfmt;
17
18         nfmt = alloca(strlen(format)+2);
19         strcpy(nfmt, format);
20         strcat(nfmt, "\n");
21         va_start(ap, format);
22         return vfprintf(stderr, nfmt, ap);
23         va_end(ap);
24 }
25
26 static void usage(const char const *cmd)
27 {
28         eprint( "usage: %s [options] [username]\n"
29                 "    -h                - show this help and exit\n"
30                 "    -o backend-option - token option \"backend:key=val\"\n"
31                 "    -f auth-file      - auth state file to read/write\n"
32                 "    -a secret | -A file-with-secret | -A -\n"
33                 "                      - 40-character hexadecimal secret\n"
34                 "    -s token-serial   - public I.D. of the token\n"
35                 "    -n nonce          - initial nonce\n"
36                 "    -l payload        - keyring unlock password\n"
37                 "    -p password       - login password"
38                 , cmd);
39 }
40
41 int main(int argc, char *argv[])
42 {
43         int c;
44         char *fn = NULL;
45         char *hsecret = NULL;
46         char *secfn = NULL;
47         char secbuf[43];
48         unsigned char bsecret[20];
49         unsigned char *secret = NULL;
50         int i;
51         char *nonce = NULL;
52         char *tokenid = NULL;
53         char *id = getlogin();
54         char *payload = "";
55         char *password = "";
56
57         while ((c = getopt(argc, argv, "ho:f:a:A:s:n:l:p:")) != -1)
58             switch (c) {
59         case 'h':
60                 usage(argv[0]);
61                 exit(EXIT_SUCCESS);
62         case 'o':
63                 if (pcsc_option(optarg)) {
64                         eprint("Option \"%s\" bad", optarg);
65                         exit(EXIT_FAILURE);
66                 }
67                 break;
68         case 'f':
69                 fn = optarg;
70                 break;
71         case 'a':
72                 if (!secfn) {
73                         hsecret = optarg;
74                 } else {
75                         eprint("-a and -A are mutually exclusive");
76                         exit(EXIT_FAILURE);
77                 }
78                 break;
79         case 'A':
80                 if (!hsecret) {
81                         secfn = optarg;
82                 } else {
83                         eprint("-A and -a are mutually exclusive");
84                         exit(EXIT_FAILURE);
85                 }
86                 break;
87         case 's':
88                 tokenid = optarg;
89                 break;
90         case 'n':
91                 nonce = optarg;
92                 break;
93         case 'l':
94                 payload = optarg;
95                 break;
96         case 'p':
97                 password = optarg;
98                 break;
99         default:
100                 usage(argv[0]);
101                 exit(EXIT_FAILURE);
102         }
103         if (optind == (argc - 1)) {
104                 id = argv[optind];
105                 optind++;
106         }
107         if (optind != argc) {
108                 usage(argv[0]);
109                 exit(EXIT_FAILURE);
110         }
111         if (secfn) {
112                 FILE *sfp;
113                 char *p;
114
115                 if (!strcmp(secfn, "-")) sfp = stdin;
116                 else sfp = fopen(secfn, "r");
117                 if (!sfp) {
118                         eprint("cannot open \"%s\": %s",
119                                 secfn, strerror(errno));
120                         exit(EXIT_FAILURE);
121                 }
122                 if (!fgets(secbuf, sizeof(secbuf), sfp)) {
123                         eprint("cannot read \"%s\": %s",
124                                 secfn, strerror(errno));
125                         exit(EXIT_FAILURE);
126                 }
127                 for (p = secbuf + strlen(secbuf) - 1;
128                         *p == '\n' || *p == '\r'; p--) *p = '\n';
129
130                 fclose(sfp);
131                 hsecret = secbuf;
132         }
133         if (!id) {
134                 eprint("cannot determine userid");
135                 exit(EXIT_FAILURE);
136         }
137         if (hsecret) {
138                 if (strlen(hsecret) != 40) {
139                         fprintf(stderr,
140                                 "secret wrong, must be exactly 40 chars\n");
141                         exit(EXIT_FAILURE);
142                 }
143                 if (strspn(hsecret, "0123456789abcdefABCDEF") != 40) {
144                         fprintf(stderr,
145                                 "secret wrong, must be hexadecimal string\n");
146                         exit(EXIT_FAILURE);
147                 }
148                 for (i = 0; i < 20; i++)
149                         sscanf(hsecret + i * 2, "%2hhx", &bsecret[i]);
150                 secret = bsecret;
151         }
152         return update_authfile(fn, tokenid, id, password, nonce,
153                                 secret, sizeof(bsecret),
154                                 (unsigned char *)payload, strlen(payload));
155 }