/* * Copyright (c) 2011, Collabora Ltd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * The names of contributors to this software may not be * used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * Author: Stef Walter */ #include "config.h" #include "compat.h" #include "debug.h" #include #include #include #include #include #include #include "message.h" #include "p11-kit.h" #include "tool.h" #include "uri.h" int p11_kit_list_modules (int argc, char *argv[]); bool verbose = false; static const char HEXC_LOWER[] = "0123456789abcdef"; static char * hex_encode (const unsigned char *data, size_t n_data) { char *result; size_t i; size_t o; result = malloc (n_data * 3 + 1); if (result == NULL) return NULL; for (i = 0, o = 0; i < n_data; i++) { if (i > 0) result[o++] = ':'; result[o++] = HEXC_LOWER[data[i] >> 4 & 0xf]; result[o++] = HEXC_LOWER[data[i] & 0xf]; } result[o] = 0; return result; } static bool is_ascii_string (const unsigned char *data, size_t n_data) { size_t i; for (i = 0; i < n_data; i++) { if (!isascii (data[i]) && (data[i] < 0x20 && !isspace (data[i]))) return false; } return true; } static void print_token_info (CK_FUNCTION_LIST_PTR module, CK_SLOT_ID slot_id) { CK_TOKEN_INFO info; char *value; CK_RV rv; rv = (module->C_GetTokenInfo) (slot_id, &info); if (rv != CKR_OK) { p11_message ("couldn't load module info: %s", p11_kit_strerror (rv)); return; } value = p11_kit_space_strdup (info.label, sizeof (info.label)); printf (" token: %s\n", value); free (value); value = p11_kit_space_strdup (info.manufacturerID, sizeof (info.manufacturerID)); printf (" manufacturer: %s\n", value); free (value); value = p11_kit_space_strdup (info.model, sizeof (info.model)); printf (" model: %s\n", value); free (value); if (is_ascii_string (info.serialNumber, sizeof (info.serialNumber))) value = p11_kit_space_strdup (info.serialNumber, sizeof (info.serialNumber)); else value = hex_encode (info.serialNumber, sizeof (info.serialNumber)); printf (" serial-number: %s\n", value); free (value); if (info.hardwareVersion.major || info.hardwareVersion.minor) printf (" hardware-version: %d.%d\n", info.hardwareVersion.major, info.hardwareVersion.minor); if (info.firmwareVersion.major || info.firmwareVersion.minor) printf (" firmware-version: %d.%d\n", info.firmwareVersion.major, info.firmwareVersion.minor); printf (" flags:\n"); #define X(x, y) if (info.flags & (x)) printf (" %s\n", (y)) X(CKF_RNG, "rng"); X(CKF_WRITE_PROTECTED, "write-protected"); X(CKF_LOGIN_REQUIRED, "login-required"); X(CKF_USER_PIN_INITIALIZED, "user-pin-initialized"); X(CKF_RESTORE_KEY_NOT_NEEDED, "restore-key-not-needed"); X(CKF_CLOCK_ON_TOKEN, "clock-on-token"); X(CKF_PROTECTED_AUTHENTICATION_PATH, "protected-authentication-path"); X(CKF_DUAL_CRYPTO_OPERATIONS, "dual-crypto-operations"); X(CKF_TOKEN_INITIALIZED, "token-initialized"); X(CKF_SECONDARY_AUTHENTICATION, "secondary-authentication"); X(CKF_USER_PIN_COUNT_LOW, "user-pin-count-low"); X(CKF_USER_PIN_FINAL_TRY, "user-pin-final-try"); X(CKF_USER_PIN_LOCKED, "user-pin-locked"); X(CKF_USER_PIN_TO_BE_CHANGED, "user-pin-to-be-changed"); X(CKF_SO_PIN_COUNT_LOW, "so-pin-count-low"); X(CKF_SO_PIN_FINAL_TRY, "so-pin-final-try"); X(CKF_SO_PIN_LOCKED, "so-pin-locked"); X(CKF_SO_PIN_TO_BE_CHANGED, "so-pin-to-be-changed"); #undef X } static void print_module_info (CK_FUNCTION_LIST_PTR module) { CK_SLOT_ID slot_list[256]; CK_ULONG i, count; CK_INFO info; char *value; CK_RV rv; rv = (module->C_GetInfo) (&info); if (rv != CKR_OK) { p11_message ("couldn't load module info: %s", p11_kit_strerror (rv)); return; } value = p11_kit_space_strdup (info.libraryDescription, sizeof (info.libraryDescription)); printf (" library-description: %s\n", value); free (value); value = p11_kit_space_strdup (info.manufacturerID, sizeof (info.manufacturerID)); printf (" library-manufacturer: %s\n", value); free (value); printf (" library-version: %d.%d\n", info.libraryVersion.major, info.libraryVersion.minor); count = sizeof (slot_list) / sizeof (slot_list[0]); rv = (module->C_GetSlotList) (CK_TRUE, slot_list, &count); if (rv != CKR_OK) { p11_message ("couldn't load module info: %s", p11_kit_strerror (rv)); return; } for (i = 0; i < count; i++) print_token_info (module, slot_list[i]); } static int print_modules (void) { CK_FUNCTION_LIST_PTR *module_list; char *name; char *path; int i; module_list = p11_kit_modules_load_and_initialize (0); if (!module_list) return 1; for (i = 0; module_list[i]; i++) { name = p11_kit_module_get_name (module_list[i]); path = p11_kit_config_option (module_list[i], "module"); printf ("%s: %s\n", name ? name : "(null)", path ? path : "(null)"); print_module_info (module_list[i]); free (name); free (path); } p11_kit_modules_finalize_and_release (module_list); return 0; } int p11_kit_list_modules (int argc, char *argv[]) { int opt; enum { opt_verbose = 'v', opt_quiet = 'q', opt_list = 'l', opt_help = 'h', }; struct option options[] = { { "verbose", no_argument, NULL, opt_verbose }, { "quiet", no_argument, NULL, opt_quiet }, { "list", no_argument, NULL, opt_list }, { "help", no_argument, NULL, opt_help }, { 0 }, }; p11_tool_desc usages[] = { { 0, "usage: p11-kit list" }, { opt_verbose, "show verbose debug output", }, { opt_quiet, "suppress command output", }, { 0 }, }; while ((opt = p11_tool_getopt (argc, argv, options)) != -1) { switch (opt) { case opt_verbose: p11_kit_be_loud (); break; case opt_quiet: p11_kit_be_quiet (); break; case opt_list: break; case opt_help: p11_tool_usage (usages, options); return 0; case '?': return 2; default: assert_not_reached (); break; } } if (argc - optind != 0) { p11_message ("extra arguments specified"); return 2; } return print_modules (); }