1 /*
2 * Copyright (c) 2011, Collabora Ltd.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 * * Redistributions in binary form must reproduce the
12 * above copyright notice, this list of conditions and
13 * the following disclaimer in the documentation and/or
14 * other materials provided with the distribution.
15 * * The names of contributors to this software may not be
16 * used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE.
31 *
32 * Author: Stef Walter <stefw@collabora.co.uk>
33 */
34
35 #include "config.h"
36
37 #include "compat.h"
38 #include "debug.h"
39
40 #include <assert.h>
41 #include <ctype.h>
42 #include <limits.h>
43 #include <stdint.h>
44 #include <string.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48
49 #include "message.h"
50 #include "p11-kit.h"
51 #include "tool.h"
52 #include "uri.h"
53
54 #ifdef ENABLE_NLS
55 #include <libintl.h>
56 #define _(x) dgettext(PACKAGE_NAME, x)
57 #else
58 #define _(x) (x)
59 #endif
60
61 int p11_kit_list_modules (int argc,
62 char *argv[]);
63
64 bool verbose = false;
65
66 static const char HEXC_LOWER[] = "0123456789abcdef";
67
68 static char *
hex_encode(const unsigned char * data,size_t n_data)69 hex_encode (const unsigned char *data,
70 size_t n_data)
71 {
72 char *result;
73 size_t i;
74 size_t o;
75
76 if ((SIZE_MAX - 1) / 3 < n_data)
77 return NULL;
78 result = malloc (n_data * 3 + 1);
79 if (result == NULL)
80 return NULL;
81
82 for (i = 0, o = 0; i < n_data; i++) {
83 if (i > 0)
84 result[o++] = ':';
85 result[o++] = HEXC_LOWER[data[i] >> 4 & 0xf];
86 result[o++] = HEXC_LOWER[data[i] & 0xf];
87 }
88
89 result[o] = 0;
90 return result;
91 }
92
93 static bool
is_ascii_string(const unsigned char * data,size_t n_data)94 is_ascii_string (const unsigned char *data,
95 size_t n_data)
96 {
97 size_t i;
98
99 for (i = 0; i < n_data; i++) {
100 if (!isascii (data[i]) &&
101 (data[i] < 0x20 && !isspace (data[i])))
102 return false;
103 }
104
105 return true;
106 }
107
108 static void
print_token_info(CK_FUNCTION_LIST_PTR module,CK_SLOT_ID slot_id)109 print_token_info (CK_FUNCTION_LIST_PTR module, CK_SLOT_ID slot_id)
110 {
111 CK_TOKEN_INFO info;
112 char *value;
113 CK_RV rv;
114
115 rv = (module->C_GetTokenInfo) (slot_id, &info);
116 if (rv != CKR_OK) {
117 p11_message (_("couldn't load module info: %s"), p11_kit_strerror (rv));
118 return;
119 }
120
121 value = p11_kit_space_strdup (info.label, sizeof (info.label));
122 printf (" token: %s\n", value);
123 free (value);
124
125 value = p11_kit_space_strdup (info.manufacturerID, sizeof (info.manufacturerID));
126 printf (" manufacturer: %s\n", value);
127 free (value);
128
129 value = p11_kit_space_strdup (info.model, sizeof (info.model));
130 printf (" model: %s\n", value);
131 free (value);
132
133 if (is_ascii_string (info.serialNumber, sizeof (info.serialNumber)))
134 value = p11_kit_space_strdup (info.serialNumber, sizeof (info.serialNumber));
135 else
136 value = hex_encode (info.serialNumber, sizeof (info.serialNumber));
137 printf (" serial-number: %s\n", value);
138 free (value);
139
140 if (info.hardwareVersion.major || info.hardwareVersion.minor)
141 printf (" hardware-version: %d.%d\n",
142 info.hardwareVersion.major,
143 info.hardwareVersion.minor);
144
145 if (info.firmwareVersion.major || info.firmwareVersion.minor)
146 printf (" firmware-version: %d.%d\n",
147 info.firmwareVersion.major,
148 info.firmwareVersion.minor);
149
150 printf (" flags:\n");
151 #define X(x, y) if (info.flags & (x)) printf (" %s\n", (y))
152 X(CKF_RNG, "rng");
153 X(CKF_WRITE_PROTECTED, "write-protected");
154 X(CKF_LOGIN_REQUIRED, "login-required");
155 X(CKF_USER_PIN_INITIALIZED, "user-pin-initialized");
156 X(CKF_RESTORE_KEY_NOT_NEEDED, "restore-key-not-needed");
157 X(CKF_CLOCK_ON_TOKEN, "clock-on-token");
158 X(CKF_PROTECTED_AUTHENTICATION_PATH, "protected-authentication-path");
159 X(CKF_DUAL_CRYPTO_OPERATIONS, "dual-crypto-operations");
160 X(CKF_TOKEN_INITIALIZED, "token-initialized");
161 X(CKF_SECONDARY_AUTHENTICATION, "secondary-authentication");
162 X(CKF_USER_PIN_COUNT_LOW, "user-pin-count-low");
163 X(CKF_USER_PIN_FINAL_TRY, "user-pin-final-try");
164 X(CKF_USER_PIN_LOCKED, "user-pin-locked");
165 X(CKF_USER_PIN_TO_BE_CHANGED, "user-pin-to-be-changed");
166 X(CKF_SO_PIN_COUNT_LOW, "so-pin-count-low");
167 X(CKF_SO_PIN_FINAL_TRY, "so-pin-final-try");
168 X(CKF_SO_PIN_LOCKED, "so-pin-locked");
169 X(CKF_SO_PIN_TO_BE_CHANGED, "so-pin-to-be-changed");
170 #undef X
171 }
172
173 static void
print_module_info(CK_FUNCTION_LIST_PTR module)174 print_module_info (CK_FUNCTION_LIST_PTR module)
175 {
176 CK_SLOT_ID slot_list[256];
177 CK_ULONG i, count;
178 CK_INFO info;
179 char *value;
180 CK_RV rv;
181
182 rv = (module->C_GetInfo) (&info);
183 if (rv != CKR_OK) {
184 p11_message (_("couldn't load module info: %s"), p11_kit_strerror (rv));
185 return;
186 }
187
188 value = p11_kit_space_strdup (info.libraryDescription,
189 sizeof (info.libraryDescription));
190 printf (" library-description: %s\n", value);
191 free (value);
192
193 value = p11_kit_space_strdup (info.manufacturerID,
194 sizeof (info.manufacturerID));
195 printf (" library-manufacturer: %s\n", value);
196 free (value);
197
198 printf (" library-version: %d.%d\n",
199 info.libraryVersion.major,
200 info.libraryVersion.minor);
201
202 count = sizeof (slot_list) / sizeof (slot_list[0]);
203 rv = (module->C_GetSlotList) (CK_TRUE, slot_list, &count);
204 if (rv != CKR_OK) {
205 p11_message (_("couldn't load module info: %s"), p11_kit_strerror (rv));
206 return;
207 }
208
209 for (i = 0; i < count; i++)
210 print_token_info (module, slot_list[i]);
211 }
212
213 static int
print_modules(void)214 print_modules (void)
215 {
216 CK_FUNCTION_LIST_PTR *module_list;
217 char *name;
218 char *path;
219 int i;
220
221 module_list = p11_kit_modules_load_and_initialize (0);
222 if (!module_list)
223 return 1;
224
225 for (i = 0; module_list[i]; i++) {
226 name = p11_kit_module_get_name (module_list[i]);
227 path = p11_kit_config_option (module_list[i], "module");
228
229 printf ("%s: %s\n",
230 name ? name : "(null)",
231 path ? path : "(null)");
232 print_module_info (module_list[i]);
233
234 free (name);
235 free (path);
236 }
237
238 p11_kit_modules_finalize_and_release (module_list);
239 return 0;
240 }
241
242 int
p11_kit_list_modules(int argc,char * argv[])243 p11_kit_list_modules (int argc,
244 char *argv[])
245 {
246 int opt;
247
248 enum {
249 opt_verbose = 'v',
250 opt_quiet = 'q',
251 opt_list = 'l',
252 opt_help = 'h',
253 };
254
255 struct option options[] = {
256 { "verbose", no_argument, NULL, opt_verbose },
257 { "quiet", no_argument, NULL, opt_quiet },
258 { "list", no_argument, NULL, opt_list },
259 { "help", no_argument, NULL, opt_help },
260 { 0 },
261 };
262
263 p11_tool_desc usages[] = {
264 { 0, "usage: p11-kit list" },
265 { opt_verbose, "show verbose debug output", },
266 { opt_quiet, "suppress command output", },
267 { 0 },
268 };
269
270 while ((opt = p11_tool_getopt (argc, argv, options)) != -1) {
271 switch (opt) {
272
273 case opt_verbose:
274 p11_kit_be_loud ();
275 break;
276
277 case opt_quiet:
278 p11_kit_be_quiet ();
279 break;
280
281 case opt_list:
282 break;
283
284 case opt_help:
285 p11_tool_usage (usages, options);
286 return 0;
287 case '?':
288 return 2;
289 default:
290 assert_not_reached ();
291 break;
292 }
293 }
294
295 if (argc - optind != 0) {
296 p11_message (_("extra arguments specified"));
297 return 2;
298 }
299
300 return print_modules ();
301 }
302