]> err.no Git - yubikey-personalization/blob - ykinfo.c
Merge tag 'v1.15.1'
[yubikey-personalization] / ykinfo.c
1 /* -*- mode:C; c-file-style: "bsd" -*- */
2 /*
3  * Copyright (c) 2012-2013 Yubico AB.
4  * All rights reserved.
5  *
6  * Some basic code copied from ykchalresp.c.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *
15  *     * Redistributions in binary form must reproduce the above
16  *       copyright notice, this list of conditions and the following
17  *       disclaimer in the documentation and/or other materials provided
18  *       with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <stdbool.h>
36
37 #include <yubikey.h>
38 #include <ykcore.h>
39 #include <ykstatus.h>
40 #include <ykpers-version.h>
41 #include <ykdef.h>
42
43 const char *usage =
44         "Usage: ykinfo [options]\n"
45         "\n"
46         "Options :\n"
47         "\n"
48         "\t-s        Get serial in decimal from YubiKey\n"
49         "\t-m        Get serial in modhex from YubiKey\n"
50         "\t-H        Get serial in hex from YubiKey\n"
51         "\t-v        Get version from YubiKey\n"
52         "\t-t        Get touchlevel from YubiKey\n"
53         "\t-1        Check if slot 1 is programmed\n"
54         "\t-2        Check if slot 2 is programmed\n"
55         "\t-p        Get programming sequence from YubiKey\n"
56         "\t-a        Get all information above\n"
57         "\n"
58         "\t-q        Only output information from YubiKey\n"
59         "\n"
60         "\t-V        Get the tool version\n"
61         "\t-h        help (this text)\n"
62         "\n"
63         "\n"
64         ;
65 const char *optstring = "asmHvtpqhV12";
66
67 static void report_yk_error(void)
68 {
69         if (yk_errno) {
70                 if (yk_errno == YK_EUSBERR) {
71                         fprintf(stderr, "USB error: %s\n",
72                                 yk_usb_strerror());
73                 } else {
74                         fprintf(stderr, "Yubikey core error: %s\n",
75                                 yk_strerror(yk_errno));
76                 }
77         }
78 }
79
80 static int parse_args(int argc, char **argv,
81                 bool *serial_dec, bool *serial_modhex, bool *serial_hex,
82                 bool *version, bool *touch_level, bool *pgm_seq, bool *quiet,
83                 bool *slot1, bool *slot2,
84                 int *exit_code)
85 {
86         int c;
87
88         while((c = getopt(argc, argv, optstring)) != -1) {
89                 switch (c) {
90                 case 'a':
91                         *serial_dec = true;
92                         *serial_modhex = true;
93                         *serial_hex = true;
94                         *version = true;
95                         *touch_level = true;
96                         *pgm_seq = true;
97                         *slot1 = true;
98                         *slot2 = true;
99                         break;
100                 case 's':
101                         *serial_dec = true;
102                         break;
103                 case 'm':
104                         *serial_modhex = true;
105                         break;
106                 case 'H':
107                         *serial_hex = true;
108                         break;
109                 case 'v':
110                         *version = true;
111                         break;
112                 case 't':
113                         *touch_level = true;
114                         break;
115                 case 'p':
116                         *pgm_seq = true;
117                         break;
118                 case 'q':
119                         *quiet = true;
120                         break;
121                 case '1':
122                         *slot1 = true;
123                         break;
124                 case '2':
125                         *slot2 = true;
126                         break;
127                 case 'V':
128                         fputs(YKPERS_VERSION_STRING "\n", stderr);
129                         *exit_code = 0;
130                         return 0;
131                 case 'h':
132                 default:
133                         fputs(usage, stderr);
134                         *exit_code = 0;
135                         return 0;
136                 }
137         }
138
139         if (!*serial_dec && !*serial_modhex && !*serial_hex &&
140                         !*version && !*touch_level && !*pgm_seq && !*slot1 && !*slot2) {
141                 /* no options at all */
142                 fputs("You must give at least one option.\n", stderr);
143                 fputs(usage, stderr);
144                 return 0;
145         }
146
147         return 1;
148 }
149
150
151 int main(int argc, char **argv)
152 {
153         YK_KEY *yk = 0;
154         bool error = true;
155         int exit_code = 0;
156
157         /* Options */
158         bool serial_dec = false;
159         bool serial_modhex = false;
160         bool serial_hex = false;
161         bool version = false;
162         bool touch_level = false;
163         bool pgm_seq = false;
164         bool slot1 = false;
165         bool slot2 = false;
166
167         bool quiet = false;
168
169         yk_errno = 0;
170
171         if (! parse_args(argc, argv,
172                                 &serial_dec, &serial_modhex, &serial_hex,
173                                 &version, &touch_level, &pgm_seq, &quiet,
174                                 &slot1, &slot2,
175                                 &exit_code))
176                 exit(exit_code);
177
178         if (!yk_init()) {
179                 exit_code = 1;
180                 goto err;
181         }
182
183         if (!(yk = yk_open_first_key())) {
184                 exit_code = 1;
185                 goto err;
186         }
187
188         if(serial_dec || serial_modhex || serial_hex) {
189                 unsigned int serial;
190                 int ret = yk_get_serial(yk, 1, 0, &serial);
191                 if(!ret) {
192                         exit_code = 1;
193                         goto err;
194                 }
195                 if(serial_dec) {
196                         if(!quiet)
197                                 printf("serial: ");
198                         printf("%d\n", serial);
199                 }
200                 if(serial_hex) {
201                         if(!quiet)
202                                 printf("serial_hex: ");
203                         printf("%x\n", serial);
204                 }
205                 if(serial_modhex) {
206                         char buf[64];
207                         char hex_serial[64];
208                         char modhex_serial[64];
209
210                         snprintf(buf, 64, "%x", serial);
211                         yubikey_hex_decode(hex_serial, buf, strlen(buf));
212                         yubikey_modhex_encode(modhex_serial, hex_serial, strlen(hex_serial));
213                         if(!quiet)
214                                 printf("serial_modhex: ");
215                         printf("%s\n", modhex_serial);
216                 }
217         }
218         if(version || touch_level || pgm_seq || slot1 || slot2) {
219                 YK_STATUS *st = ykds_alloc();
220                 if(!yk_get_status(yk, st)) {
221                         ykds_free(st);
222                         exit_code = 1;
223                         goto err;
224                 }
225
226                 if(version) {
227                         if(!quiet)
228                                 printf("version: ");
229                         printf("%d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st));
230                 }
231                 if(touch_level) {
232                         if(!quiet)
233                                 printf("touch_level: ");
234                         printf("%d\n", ykds_touch_level(st));
235                 }
236                 if(pgm_seq) {
237                         if(!quiet)
238                                 printf("programming_sequence: ");
239                         printf("%d\n", ykds_pgm_seq(st));
240                 }
241                 if(slot1) {
242                         if(!quiet)
243                                 printf("slot1_status: ");
244                         printf("%d\n", (ykds_touch_level(st) & CONFIG1_VALID) == CONFIG1_VALID);
245                 }
246                 if(slot2) {
247                         if(!quiet)
248                                 printf("slot2_status: ");
249                         printf("%d\n", (ykds_touch_level(st) & CONFIG2_VALID) == CONFIG2_VALID);
250                 }
251                 ykds_free(st);
252         }
253
254         exit_code = 0;
255         error = false;
256
257 err:
258         if (error || exit_code != 0) {
259                 report_yk_error();
260         }
261
262         if (yk && !yk_close_key(yk)) {
263                 report_yk_error();
264                 exit_code = 2;
265         }
266
267         if (!yk_release()) {
268                 report_yk_error();
269                 exit_code = 2;
270         }
271
272         exit(exit_code);
273 }