2020-11-29 00:59:21 +03:00
/* SPDX-License-Identifier: LGPL-2.1-or-later */
# include "cryptenroll-list.h"
# include "cryptenroll.h"
# include "format-table.h"
# include "parse-util.h"
2023-03-27 17:51:00 +03:00
struct keyslot_metadata {
int slot ;
const char * type ;
} ;
2020-11-29 00:59:21 +03:00
2023-03-27 17:51:00 +03:00
int list_enrolled ( struct crypt_device * cd ) {
_cleanup_free_ struct keyslot_metadata * keyslot_metadata = NULL ;
2020-11-29 00:59:21 +03:00
_cleanup_ ( table_unrefp ) Table * t = NULL ;
2021-05-19 00:01:32 +03:00
size_t n_keyslot_metadata = 0 ;
2020-11-29 00:59:21 +03:00
int slot_max , r ;
TableCell * cell ;
assert ( cd ) ;
/* First step, find out all currently used slots */
assert_se ( ( slot_max = crypt_keyslot_max ( CRYPT_LUKS2 ) ) > 0 ) ;
for ( int slot = 0 ; slot < slot_max ; slot + + ) {
crypt_keyslot_info status ;
status = crypt_keyslot_status ( cd , slot ) ;
if ( ! IN_SET ( status , CRYPT_SLOT_ACTIVE , CRYPT_SLOT_ACTIVE_LAST ) )
continue ;
2021-05-19 00:01:32 +03:00
if ( ! GREEDY_REALLOC ( keyslot_metadata , n_keyslot_metadata + 1 ) )
2020-11-29 00:59:21 +03:00
return log_oom ( ) ;
keyslot_metadata [ n_keyslot_metadata + + ] = ( struct keyslot_metadata ) {
. slot = slot ,
} ;
}
/* Second step, enumerate through all tokens, and update the slot table, indicating what kind of
* token they are assigned to */
2020-12-29 02:50:16 +03:00
for ( int token = 0 ; token < sym_crypt_token_max ( CRYPT_LUKS2 ) ; token + + ) {
2020-11-29 00:59:21 +03:00
_cleanup_ ( json_variant_unrefp ) JsonVariant * v = NULL ;
const char * type ;
JsonVariant * w , * z ;
EnrollType et ;
r = cryptsetup_get_token_as_json ( cd , token , NULL , & v ) ;
if ( IN_SET ( r , - ENOENT , - EINVAL ) )
continue ;
if ( r < 0 ) {
log_warning_errno ( r , " Failed to read JSON token data off disk, ignoring: %m " ) ;
continue ;
}
w = json_variant_by_key ( v , " type " ) ;
if ( ! w | | ! json_variant_is_string ( w ) ) {
log_warning ( " Token JSON data lacks type field, ignoring. " ) ;
continue ;
}
et = luks2_token_type_from_string ( json_variant_string ( w ) ) ;
if ( et < 0 )
type = " other " ;
else
type = enroll_type_to_string ( et ) ;
w = json_variant_by_key ( v , " keyslots " ) ;
if ( ! w | | ! json_variant_is_array ( w ) ) {
log_warning ( " Token JSON data lacks keyslots field, ignoring. " ) ;
continue ;
}
JSON_VARIANT_ARRAY_FOREACH ( z , w ) {
unsigned u ;
if ( ! json_variant_is_string ( z ) ) {
log_warning ( " Token JSON data's keyslot field is not an array of strings, ignoring. " ) ;
continue ;
}
r = safe_atou ( json_variant_string ( z ) , & u ) ;
if ( r < 0 ) {
2022-06-03 18:09:23 +03:00
log_warning_errno ( r , " Token JSON data's keyslot field is not an integer formatted as string, ignoring. " ) ;
2020-11-29 00:59:21 +03:00
continue ;
}
for ( size_t i = 0 ; i < n_keyslot_metadata ; i + + ) {
if ( ( unsigned ) keyslot_metadata [ i ] . slot ! = u )
continue ;
if ( keyslot_metadata [ i ] . type ) /* Slot claimed multiple times? */
keyslot_metadata [ i ] . type = POINTER_MAX ;
else
keyslot_metadata [ i ] . type = type ;
}
}
}
/* Finally, create a table out of it all */
t = table_new ( " slot " , " type " ) ;
if ( ! t )
return log_oom ( ) ;
assert_se ( cell = table_get_cell ( t , 0 , 0 ) ) ;
( void ) table_set_align_percent ( t , cell , 100 ) ;
for ( size_t i = 0 ; i < n_keyslot_metadata ; i + + ) {
r = table_add_many (
t ,
TABLE_INT , keyslot_metadata [ i ] . slot ,
TABLE_STRING , keyslot_metadata [ i ] . type = = POINTER_MAX ? " conflict " :
keyslot_metadata [ i ] . type ? : " password " ) ;
if ( r < 0 )
return table_log_add_error ( r ) ;
}
2023-12-25 12:34:57 +03:00
if ( table_isempty ( t ) ) {
2020-11-29 00:59:21 +03:00
log_info ( " No slots found. " ) ;
return 0 ;
}
r = table_print ( t , stdout ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to show slot table: %m " ) ;
return 0 ;
}