homectl: add --pkcs11-uri=auto and --pkcs-11-uri=list support
We have the same for FIDO2 devices, for listing suitable devices, or picking the right one automatically, let's add that for PKCS11 too.
This commit is contained in:
parent
2af3966af3
commit
0eb3be4644
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "format-table.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "homectl-pkcs11.h"
|
||||
#include "libcrypt-util.h"
|
||||
|
@ -339,3 +340,141 @@ int identity_add_pkcs11_key_data(JsonVariant **v, const char *uri) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_P11KIT
|
||||
static int list_callback(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
CK_SLOT_ID slot_id,
|
||||
const CK_SLOT_INFO *slot_info,
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
P11KitUri *uri,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_free_ char *token_uri_string = NULL, *token_label = NULL, *token_manufacturer_id = NULL, *token_model = NULL;
|
||||
_cleanup_(p11_kit_uri_freep) P11KitUri *token_uri = NULL;
|
||||
Table *t = userdata;
|
||||
int uri_result, r;
|
||||
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
|
||||
/* We only care about hardware devices here with a token inserted. Let's filter everything else
|
||||
* out. (Note that the user can explicitly specify non-hardware tokens if they like, but during
|
||||
* enumeration we'll filter those, since software tokens are typically the system certificate store
|
||||
* and such, and it's typically not what people want to bind their home directories to.) */
|
||||
if (!FLAGS_SET(token_info->flags, CKF_HW_SLOT|CKF_TOKEN_PRESENT))
|
||||
return -EAGAIN;
|
||||
|
||||
token_label = pkcs11_token_label(token_info);
|
||||
if (!token_label)
|
||||
return log_oom();
|
||||
|
||||
token_manufacturer_id = pkcs11_token_manufacturer_id(token_info);
|
||||
if (!token_manufacturer_id)
|
||||
return log_oom();
|
||||
|
||||
token_model = pkcs11_token_model(token_info);
|
||||
if (!token_model)
|
||||
return log_oom();
|
||||
|
||||
token_uri = uri_from_token_info(token_info);
|
||||
if (!token_uri)
|
||||
return log_oom();
|
||||
|
||||
uri_result = p11_kit_uri_format(token_uri, P11_KIT_URI_FOR_ANY, &token_uri_string);
|
||||
if (uri_result != P11_KIT_URI_OK)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN), "Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
|
||||
|
||||
r = table_add_many(
|
||||
t,
|
||||
TABLE_STRING, token_uri_string,
|
||||
TABLE_STRING, token_label,
|
||||
TABLE_STRING, token_manufacturer_id,
|
||||
TABLE_STRING, token_model);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return -EAGAIN; /* keep scanning */
|
||||
}
|
||||
#endif
|
||||
|
||||
int list_pkcs11_tokens(void) {
|
||||
#if HAVE_P11KIT
|
||||
_cleanup_(table_unrefp) Table *t = NULL;
|
||||
int r;
|
||||
|
||||
t = table_new("uri", "label", "manufacturer", "model");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
r = pkcs11_find_token(NULL, list_callback, t);
|
||||
if (r < 0 && r != -EAGAIN)
|
||||
return r;
|
||||
|
||||
if (table_get_rows(t) <= 1) {
|
||||
log_info("No suitable PKCS#11 tokens found.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = table_print(t, stdout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to show device table: %m");
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_error_errno(EOPNOTSUPP, "PKCS#11 tokens not supported on this build.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_P11KIT
|
||||
static int auto_callback(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
CK_SLOT_ID slot_id,
|
||||
const CK_SLOT_INFO *slot_info,
|
||||
const CK_TOKEN_INFO *token_info,
|
||||
P11KitUri *uri,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(p11_kit_uri_freep) P11KitUri *token_uri = NULL;
|
||||
char **t = userdata;
|
||||
int uri_result;
|
||||
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
|
||||
if (!FLAGS_SET(token_info->flags, CKF_HW_SLOT|CKF_TOKEN_PRESENT))
|
||||
return -EAGAIN;
|
||||
|
||||
if (*t)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ),
|
||||
"More than one suitable PKCS#11 token found.");
|
||||
|
||||
token_uri = uri_from_token_info(token_info);
|
||||
if (!token_uri)
|
||||
return log_oom();
|
||||
|
||||
uri_result = p11_kit_uri_format(token_uri, P11_KIT_URI_FOR_ANY, t);
|
||||
if (uri_result != P11_KIT_URI_OK)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN), "Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int find_pkcs11_token_auto(char **ret) {
|
||||
#if HAVE_P11KIT
|
||||
int r;
|
||||
|
||||
r = pkcs11_find_token(NULL, auto_callback, ret);
|
||||
if (r == -EAGAIN)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "No suitable PKCS#11 tokens found.");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return log_error_errno(EOPNOTSUPP, "PKCS#11 tokens not supported on this build.");
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -6,3 +6,6 @@
|
|||
int identity_add_token_pin(JsonVariant **v, const char *pin);
|
||||
|
||||
int identity_add_pkcs11_key_data(JsonVariant **v, const char *token_uri);
|
||||
|
||||
int list_pkcs11_tokens(void);
|
||||
int find_pkcs11_token_auto(char **ret);
|
||||
|
|
|
@ -3098,6 +3098,9 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
case ARG_PKCS11_TOKEN_URI: {
|
||||
const char *p;
|
||||
|
||||
if (streq(optarg, "list"))
|
||||
return list_pkcs11_tokens();
|
||||
|
||||
/* If --pkcs11-token-uri= is specified we always drop everything old */
|
||||
FOREACH_STRING(p, "pkcs11TokenUri", "pkcs11EncryptedKey") {
|
||||
r = drop_from_identity(p);
|
||||
|
@ -3110,10 +3113,19 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!pkcs11_uri_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid PKCS#11 URI: %s", optarg);
|
||||
if (streq(optarg, "auto")) {
|
||||
_cleanup_free_ char *found = NULL;
|
||||
|
||||
r = strv_extend(&arg_pkcs11_token_uri, optarg);
|
||||
r = find_pkcs11_token_auto(&found);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strv_consume(&arg_pkcs11_token_uri, TAKE_PTR(found));
|
||||
} else {
|
||||
if (!pkcs11_uri_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid PKCS#11 URI: %s", optarg);
|
||||
|
||||
r = strv_extend(&arg_pkcs11_token_uri, optarg);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -151,6 +151,28 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info) {
|
|||
return t;
|
||||
}
|
||||
|
||||
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info) {
|
||||
char *t;
|
||||
|
||||
t = strndup((char*) token_info->manufacturerID, sizeof(token_info->manufacturerID));
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
strstrip(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info) {
|
||||
char *t;
|
||||
|
||||
t = strndup((char*) token_info->model, sizeof(token_info->model));
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
strstrip(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
int pkcs11_token_login(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
|
@ -165,9 +187,8 @@ int pkcs11_token_login(
|
|||
_cleanup_free_ char *token_uri_string = NULL, *token_uri_escaped = NULL, *id = NULL, *token_label = NULL;
|
||||
_cleanup_(p11_kit_uri_freep) P11KitUri *token_uri = NULL;
|
||||
CK_TOKEN_INFO updated_token_info;
|
||||
int uri_result;
|
||||
int uri_result, r;
|
||||
CK_RV rv;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(token_info);
|
||||
|
@ -703,7 +724,6 @@ static int token_process(
|
|||
assert(m);
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
assert(search_uri);
|
||||
|
||||
token_label = pkcs11_token_label(token_info);
|
||||
if (!token_label)
|
||||
|
@ -741,7 +761,6 @@ static int slot_process(
|
|||
CK_RV rv;
|
||||
|
||||
assert(m);
|
||||
assert(search_uri);
|
||||
|
||||
/* We return -EAGAIN for all failures we can attribute to a specific slot in some way, so that the
|
||||
* caller might try other slots before giving up. */
|
||||
|
@ -787,7 +806,7 @@ static int slot_process(
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!p11_kit_uri_match_token_info(search_uri, &token_info)) {
|
||||
if (search_uri && !p11_kit_uri_match_token_info(search_uri, &token_info)) {
|
||||
log_debug("Found non-matching token with URI %s.", token_uri_string);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
@ -821,7 +840,6 @@ static int module_process(
|
|||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(search_uri);
|
||||
|
||||
/* We ignore most errors from modules here, in order to skip over faulty modules: one faulty module
|
||||
* should not have the effect that we don't try the others anymore. We indicate such per-module
|
||||
|
@ -884,14 +902,14 @@ int pkcs11_find_token(
|
|||
_cleanup_(p11_kit_uri_freep) P11KitUri *search_uri = NULL;
|
||||
int r;
|
||||
|
||||
assert(pkcs11_uri);
|
||||
|
||||
/* Execute the specified callback for each matching token found. If nothing is found returns
|
||||
* -EAGAIN. Logs about all errors, except for EAGAIN, which the caller has to log about. */
|
||||
|
||||
r = uri_from_string(pkcs11_uri, &search_uri);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PKCS#11 URI '%s': %m", pkcs11_uri);
|
||||
if (pkcs11_uri) {
|
||||
r = uri_from_string(pkcs11_uri, &search_uri);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PKCS#11 URI '%s': %m", pkcs11_uri);
|
||||
}
|
||||
|
||||
modules = p11_kit_modules_load_and_initialize(0);
|
||||
if (!modules)
|
||||
|
|
|
@ -27,6 +27,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(CK_FUNCTION_LIST**, p11_kit_modules_finalize_and_rel
|
|||
CK_RV pkcs11_get_slot_list_malloc(CK_FUNCTION_LIST *m, CK_SLOT_ID **ret_slotids, CK_ULONG *ret_n_slotids);
|
||||
|
||||
char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info);
|
||||
char *pkcs11_token_model(const CK_TOKEN_INFO *token_info);
|
||||
|
||||
int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *keyname, usec_t until, char **ret_used_pin);
|
||||
|
||||
|
|
Loading…
Reference in New Issue