21
21
#include <sys/zfs_context.h>
22
22
#include <sys/fs/zfs.h>
23
23
#include <sys/dsl_crypt.h>
24
+ #include <sys/wait.h>
24
25
#include <libintl.h>
25
26
#include <termios.h>
26
27
#include <signal.h>
@@ -471,6 +472,107 @@ get_key_material_raw(FILE *fd, zfs_keyformat_t keyformat,
471
472
return (ret );
472
473
}
473
474
475
+ static int
476
+ execute_key_provider_exec (libzfs_handle_t * hdl , const char * executable ,
477
+ const char * fsname , zfs_keyformat_t keyformat , int * outfd )
478
+ {
479
+ int ret = 0 , status , compipe [2 ];
480
+ char * const argv [] =
481
+ {(char * )executable , (char * )fsname , /*(char *)keyformat,*/ NULL };
482
+ pid_t child ;
483
+
484
+ if (pipe2 (compipe , O_NONBLOCK | O_CLOEXEC ) != 0 ) {
485
+ ret = errno ;
486
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
487
+ "Failed to create key provider pipes: %s" ), strerror (ret ));
488
+ return (ret );
489
+ }
490
+
491
+ switch ((child = fork ())) {
492
+ case -1 :
493
+ ret = errno ;
494
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
495
+ "Failed to start key provider %s: %s" ),
496
+ executable , strerror (ret ));
497
+ (void ) close (compipe [1 ]);
498
+ goto end ;
499
+ case 0 : /* child */
500
+ (void ) dup2 (compipe [1 ], 3 );
501
+
502
+ (void ) execvp (executable , argv );
503
+
504
+ status = write (3 , strerror (errno ), strlen (strerror (errno )));
505
+ _exit (-1 );
506
+ }
507
+
508
+ /* parent */
509
+ (void ) close (compipe [1 ]);
510
+
511
+ while (waitpid (child , & status , 0 ) == -1 )
512
+ if (errno != EINTR ) {
513
+ ret = errno ;
514
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
515
+ "Failed to wait for key provider %s (%d): %s" ),
516
+ executable , child , strerror (ret ));
517
+
518
+ goto end ;
519
+ }
520
+
521
+ if (WIFSIGNALED (status )) {
522
+ ret = EZFS_INTR ;
523
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
524
+ "Key provider %s killed by %s" ),
525
+ executable , strsignal (WTERMSIG (status )));
526
+ } else if (WEXITSTATUS (status ) == 0xff ) {
527
+ char errbuf [128 ] = {0 };
528
+ status = read (compipe [0 ], errbuf , sizeof (errbuf ) - 1 );
529
+
530
+ ret = ENOEXEC ;
531
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
532
+ "Failed to start key provider %s: %s" ),
533
+ executable , strlen (errbuf ) ? errbuf : "(?)" );
534
+ } else if (WEXITSTATUS (status ) != 0 ) {
535
+ ret = ECANCELED ;
536
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
537
+ "Key provider %s failed with %d" ),
538
+ executable , WEXITSTATUS (status ));
539
+ }
540
+
541
+ end :
542
+ if (ret == 0 )
543
+ * outfd = compipe [0 ];
544
+ else
545
+ (void ) close (compipe [0 ]);
546
+ errno = 0 ;
547
+ return (ret );
548
+ }
549
+
550
+ static int
551
+ get_key_material_exec (libzfs_handle_t * hdl , char * executable ,
552
+ const char * fsname , zfs_keyformat_t keyformat ,
553
+ uint8_t * * restrict buf , size_t * restrict len_out )
554
+ {
555
+ int ret = 0 , rdpipe = -1 ;
556
+ FILE * f ;
557
+
558
+ if ((ret = execute_key_provider_exec (hdl , executable , fsname , keyformat , & rdpipe )) != 0 )
559
+ return (ret );
560
+
561
+ if ((f = fdopen (rdpipe , "r" )) == NULL ) {
562
+ ret = errno ;
563
+ errno = 0 ;
564
+ zfs_error_aux (hdl , dgettext (TEXT_DOMAIN ,
565
+ "Failed to fdopen key provider pipe" ));
566
+
567
+ (void ) close (rdpipe );
568
+ return (ret );
569
+ }
570
+
571
+ ret = get_key_material_raw (f , keyformat , buf , len_out );
572
+ (void ) fclose (f );
573
+ return (ret );
574
+ }
575
+
474
576
static int
475
577
get_key_material_file (libzfs_handle_t * hdl , const char * uri ,
476
578
const char * fsname , zfs_keyformat_t keyformat , boolean_t newkey ,
@@ -677,8 +779,9 @@ get_key_material_https(libzfs_handle_t *hdl, const char *uri,
677
779
*/
678
780
static int
679
781
get_key_material (libzfs_handle_t * hdl , boolean_t do_verify , boolean_t newkey ,
680
- zfs_keyformat_t keyformat , char * keylocation , const char * fsname ,
681
- uint8_t * * km_out , size_t * kmlen_out , boolean_t * can_retry_out )
782
+ zfs_keyformat_t keyformat , char * keylocation , char * executable ,
783
+ const char * fsname , uint8_t * * km_out , size_t * kmlen_out ,
784
+ boolean_t * can_retry_out )
682
785
{
683
786
int ret ;
684
787
zfs_keylocation_t keyloc = ZFS_KEYLOCATION_NONE ;
@@ -697,7 +800,11 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey,
697
800
/* open the appropriate file descriptor */
698
801
switch (keyloc ) {
699
802
case ZFS_KEYLOCATION_PROMPT :
700
- if (isatty (fileno (stdin ))) {
803
+ if (executable != NULL ) {
804
+ can_retry = B_TRUE ;
805
+ ret = get_key_material_exec (hdl , executable , fsname ,
806
+ keyformat , & km , & kmlen );
807
+ } else if (isatty (fileno (stdin ))) {
701
808
can_retry = keyformat != ZFS_KEYFORMAT_RAW ;
702
809
ret = get_key_interactive (hdl , fsname , keyformat ,
703
810
do_verify , newkey , & km , & kmlen );
@@ -854,7 +961,7 @@ populate_create_encryption_params_nvlists(libzfs_handle_t *hdl,
854
961
855
962
/* get key material from keyformat and keylocation */
856
963
ret = get_key_material (hdl , B_TRUE , newkey , keyformat , keylocation ,
857
- fsname , & key_material , & key_material_len , NULL );
964
+ NULL , fsname , & key_material , & key_material_len , NULL );
858
965
if (ret != 0 )
859
966
goto error ;
860
967
@@ -1214,7 +1321,7 @@ load_keys_cb(zfs_handle_t *zhp, void *arg)
1214
1321
/* Attempt to load the key. Record status in cb. */
1215
1322
cb -> cb_numattempted ++ ;
1216
1323
1217
- ret = zfs_crypto_load_key (zhp , B_FALSE , NULL );
1324
+ ret = zfs_crypto_load_key (zhp , B_FALSE , NULL , NULL );
1218
1325
if (ret )
1219
1326
cb -> cb_numfailed ++ ;
1220
1327
@@ -1266,7 +1373,7 @@ zfs_crypto_attempt_load_keys(libzfs_handle_t *hdl, char *fsname)
1266
1373
}
1267
1374
1268
1375
int
1269
- zfs_crypto_load_key (zfs_handle_t * zhp , boolean_t noop , char * alt_keylocation )
1376
+ zfs_crypto_load_key (zfs_handle_t * zhp , boolean_t noop , char * alt_keylocation , char * executable )
1270
1377
{
1271
1378
int ret , attempts = 0 ;
1272
1379
char errbuf [1024 ];
@@ -1359,7 +1466,7 @@ zfs_crypto_load_key(zfs_handle_t *zhp, boolean_t noop, char *alt_keylocation)
1359
1466
1360
1467
/* get key material from key format and location */
1361
1468
ret = get_key_material (zhp -> zfs_hdl , B_FALSE , B_FALSE , keyformat ,
1362
- keylocation , zfs_get_name (zhp ), & key_material , & key_material_len ,
1469
+ keylocation , executable , zfs_get_name (zhp ), & key_material , & key_material_len ,
1363
1470
& can_retry );
1364
1471
if (ret != 0 )
1365
1472
goto error ;
0 commit comments