2 * e4crypt.c - ext4 encryption management utility
4 * Copyright (c) 2014 Google, Inc.
5 * SHA512 implementation from libtomcrypt.
7 * Authors: Michael Halcrow <mhalcrow@google.com>,
8 * Ildar Muslukhov <ildarm@google.com>
11 #ifndef _LARGEFILE_SOURCE
12 #define _LARGEFILE_SOURCE
15 #ifndef _LARGEFILE64_SOURCE
16 #define _LARGEFILE64_SOURCE
34 #include <sys/ioctl.h>
36 #include <sys/types.h>
41 #if !defined(HAVE_ADD_KEY) || !defined(HAVE_KEYCTL)
42 #include <sys/syscall.h>
48 #include "ext2fs/ext2_fs.h"
49 #include "ext2fs/ext2fs.h"
50 #include "uuid/uuid.h"
52 /* special process keyring shortcut IDs */
53 #define KEY_SPEC_THREAD_KEYRING -1
54 #define KEY_SPEC_PROCESS_KEYRING -2
55 #define KEY_SPEC_SESSION_KEYRING -3
56 #define KEY_SPEC_USER_KEYRING -4
57 #define KEY_SPEC_USER_SESSION_KEYRING -5
58 #define KEY_SPEC_GROUP_KEYRING -6
60 #define KEYCTL_GET_KEYRING_ID 0
61 #define KEYCTL_JOIN_SESSION_KEYRING 1
62 #define KEYCTL_DESCRIBE 6
63 #define KEYCTL_SEARCH 10
64 #define KEYCTL_SESSION_TO_PARENT 18
66 typedef __s32 key_serial_t
;
68 #define EXT4_KEY_REF_STR_BUF_SIZE ((EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1)
70 #ifndef EXT4_IOC_GET_ENCRYPTION_PWSALT
71 #define EXT4_IOC_GET_ENCRYPTION_PWSALT _IOW('f', 20, __u8[16])
74 #define OPT_VERBOSE 0x0001
75 #define OPT_QUIET 0x0002
80 static long keyctl(int cmd
, ...)
83 unsigned long arg2
, arg3
, arg4
, arg5
;
86 arg2
= va_arg(va
, unsigned long);
87 arg3
= va_arg(va
, unsigned long);
88 arg4
= va_arg(va
, unsigned long);
89 arg5
= va_arg(va
, unsigned long);
91 return syscall(__NR_keyctl
, cmd
, arg2
, arg3
, arg4
, arg5
);
96 static key_serial_t
add_key(const char *type
, const char *description
,
97 const void *payload
, size_t plen
,
100 return syscall(__NR_add_key
, type
, description
, payload
,
105 static const unsigned char *hexchars
= (const unsigned char *) "0123456789abcdef";
106 static const size_t hexchars_size
= 16;
108 #define SHA512_LENGTH 64
109 #define EXT2FS_KEY_TYPE_LOGON "logon"
110 #define EXT2FS_KEY_DESC_PREFIX "ext4:"
111 #define EXT2FS_KEY_DESC_PREFIX_SIZE 5
113 #define EXT4_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct ext4_encryption_policy)
114 #define EXT4_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct ext4_encryption_policy)
116 static int int_log2(int arg
)
128 static void validate_paths(int argc
, char *argv
[], int path_start_index
)
134 for (x
= path_start_index
; x
< argc
; x
++) {
135 int ret
= access(argv
[x
], W_OK
);
142 ret
= stat(argv
[x
], &st
);
145 if (!S_ISDIR(st
.st_mode
)) {
146 fprintf(stderr
, "%s is not a directory\n", argv
[x
]);
154 static int hex2byte(const char *hex
, size_t hex_size
, unsigned char *bytes
,
158 unsigned char *h
, *l
;
162 for (x
= 0; x
< hex_size
; x
+= 2) {
163 h
= memchr(hexchars
, hex
[x
], hexchars_size
);
166 l
= memchr(hexchars
, hex
[x
+ 1], hexchars_size
);
169 if ((x
>> 1) >= bytes_size
)
171 bytes
[x
>> 1] = (((unsigned char)(h
- hexchars
) << 4) +
172 (unsigned char)(l
- hexchars
));
182 char key_ref_str
[EXT4_KEY_REF_STR_BUF_SIZE
];
183 unsigned char key_desc
[EXT4_KEY_DESCRIPTOR_SIZE
];
184 unsigned char key
[EXT4_MAX_KEY_SIZE
];
187 struct salt
*salt_list
;
190 char in_passphrase
[EXT4_MAX_PASSPHRASE_SIZE
];
192 static struct salt
*find_by_salt(unsigned char *salt
, size_t salt_len
)
197 for (i
= 0, p
= salt_list
; i
< num_salt
; i
++, p
++)
198 if ((p
->salt_len
== salt_len
) &&
199 !memcmp(p
->salt
, salt
, salt_len
))
204 static void add_salt(unsigned char *salt
, size_t salt_len
)
206 if (find_by_salt(salt
, salt_len
))
208 if (num_salt
>= max_salt
) {
209 max_salt
= num_salt
+ 10;
210 salt_list
= realloc(salt_list
, max_salt
* sizeof(struct salt
));
212 fprintf(stderr
, "Couldn't allocate salt list\n");
216 salt_list
[num_salt
].salt
= salt
;
217 salt_list
[num_salt
].salt_len
= salt_len
;
221 static void clear_secrets(void)
224 memset(salt_list
, 0, sizeof(struct salt
) * max_salt
);
228 memset(in_passphrase
, 0, sizeof(in_passphrase
));
231 static void die_signal_handler(int signum
EXT2FS_ATTR((unused
)),
232 siginfo_t
*siginfo
EXT2FS_ATTR((unused
)),
233 void *context
EXT2FS_ATTR((unused
)))
239 static void sigcatcher_setup(void)
243 memset(&sa
, 0, sizeof(struct sigaction
));
244 sa
.sa_sigaction
= die_signal_handler
;
245 sa
.sa_flags
= SA_SIGINFO
;
247 sigaction(SIGHUP
, &sa
, 0);
248 sigaction(SIGINT
, &sa
, 0);
249 sigaction(SIGQUIT
, &sa
, 0);
250 sigaction(SIGFPE
, &sa
, 0);
251 sigaction(SIGILL
, &sa
, 0);
252 sigaction(SIGBUS
, &sa
, 0);
253 sigaction(SIGSEGV
, &sa
, 0);
254 sigaction(SIGABRT
, &sa
, 0);
255 sigaction(SIGPIPE
, &sa
, 0);
256 sigaction(SIGALRM
, &sa
, 0);
257 sigaction(SIGTERM
, &sa
, 0);
258 sigaction(SIGUSR1
, &sa
, 0);
259 sigaction(SIGUSR2
, &sa
, 0);
260 sigaction(SIGPOLL
, &sa
, 0);
261 sigaction(SIGPROF
, &sa
, 0);
262 sigaction(SIGSYS
, &sa
, 0);
263 sigaction(SIGTRAP
, &sa
, 0);
264 sigaction(SIGVTALRM
, &sa
, 0);
265 sigaction(SIGXCPU
, &sa
, 0);
266 sigaction(SIGXFSZ
, &sa
, 0);
270 #define PARSE_FLAGS_NOTSUPP_OK 0x0001
271 #define PARSE_FLAGS_FORCE_FN 0x0002
273 static void parse_salt(char *salt_str
, int flags
)
275 unsigned char buf
[EXT4_MAX_SALT_SIZE
];
277 unsigned char *salt_buf
;
278 int fd
, ret
, salt_len
= 0;
280 if (flags
& PARSE_FLAGS_FORCE_FN
)
281 goto salt_from_filename
;
282 if (strncmp(cp
, "s:", 2) == 0) {
284 salt_len
= strlen(cp
);
285 if (salt_len
>= EXT4_MAX_SALT_SIZE
)
287 strncpy((char *) buf
, cp
, sizeof(buf
));
288 } else if (cp
[0] == '/') {
290 fd
= open(cp
, O_RDONLY
| O_DIRECTORY
);
291 if (fd
== -1 && errno
== ENOTDIR
)
292 fd
= open(cp
, O_RDONLY
);
297 ret
= ioctl(fd
, EXT4_IOC_GET_ENCRYPTION_PWSALT
, &buf
);
300 if (flags
& PARSE_FLAGS_NOTSUPP_OK
)
302 perror("EXT4_IOC_GET_ENCRYPTION_PWSALT");
305 if (options
& OPT_VERBOSE
) {
307 uuid_unparse(buf
, tmp
);
308 printf("%s has pw salt %s\n", cp
, tmp
);
311 } else if (strncmp(cp
, "f:", 2) == 0) {
313 goto salt_from_filename
;
314 } else if (strncmp(cp
, "0x", 2) == 0) {
315 unsigned char *h
, *l
;
321 if (salt_len
>= EXT4_MAX_SALT_SIZE
)
323 h
= memchr(hexchars
, *cp
++, hexchars_size
);
324 l
= memchr(hexchars
, *cp
++, hexchars_size
);
328 (((unsigned char)(h
- hexchars
) << 4) +
329 (unsigned char)(l
- hexchars
));
331 } else if (uuid_parse(cp
, buf
) == 0) {
335 fprintf(stderr
, "Invalid salt: %s\n", salt_str
);
338 salt_buf
= malloc(salt_len
);
340 fprintf(stderr
, "Couldn't allocate salt\n");
343 memcpy(salt_buf
, buf
, salt_len
);
344 add_salt(salt_buf
, salt_len
);
347 static void set_policy(struct salt
*set_salt
, int pad
,
348 int argc
, char *argv
[], int path_start_index
)
351 struct ext4_encryption_policy policy
;
357 if ((pad
!= 4) && (pad
!= 8) &&
358 (pad
!= 16) && (pad
!= 32)) {
359 fprintf(stderr
, "Invalid padding %d\n", pad
);
363 for (x
= path_start_index
; x
< argc
; x
++) {
364 fd
= open(argv
[x
], O_DIRECTORY
);
372 if (ioctl(fd
, EXT4_IOC_GET_ENCRYPTION_PWSALT
,
374 perror("EXT4_IOC_GET_ENCRYPTION_PWSALT");
377 salt
= find_by_salt(uu
, sizeof(uu
));
379 fprintf(stderr
, "Couldn't find salt!?!\n");
384 policy
.contents_encryption_mode
=
385 EXT4_ENCRYPTION_MODE_AES_256_XTS
;
386 policy
.filenames_encryption_mode
=
387 EXT4_ENCRYPTION_MODE_AES_256_CTS
;
388 policy
.flags
= int_log2(pad
>> 2);
389 memcpy(policy
.master_key_descriptor
, salt
->key_desc
,
390 EXT4_KEY_DESCRIPTOR_SIZE
);
391 rc
= ioctl(fd
, EXT4_IOC_SET_ENCRYPTION_POLICY
, &policy
);
394 printf("Error [%s] setting policy.\nThe key descriptor "
395 "[%s] may not match the existing encryption "
396 "context for directory [%s].\n",
397 strerror(errno
), salt
->key_ref_str
, argv
[x
]);
400 printf("Key with descriptor [%s] applied to %s.\n",
401 salt
->key_ref_str
, argv
[x
]);
405 static void pbkdf2_sha512(const char *passphrase
, struct salt
*salt
,
407 unsigned char derived_key
[EXT4_MAX_KEY_SIZE
])
409 size_t passphrase_size
= strlen(passphrase
);
410 unsigned char buf
[SHA512_LENGTH
+ EXT4_MAX_PASSPHRASE_SIZE
] = {0};
411 unsigned char tempbuf
[SHA512_LENGTH
] = {0};
412 char final
[SHA512_LENGTH
] = {0};
413 unsigned char saltbuf
[EXT4_MAX_SALT_SIZE
+ EXT4_MAX_PASSPHRASE_SIZE
] = {0};
414 int actual_buf_len
= SHA512_LENGTH
+ passphrase_size
;
415 int actual_saltbuf_len
= EXT4_MAX_SALT_SIZE
+ passphrase_size
;
417 __u32
*final_u32
= (__u32
*)final
;
418 __u32
*temp_u32
= (__u32
*)tempbuf
;
420 if (passphrase_size
> EXT4_MAX_PASSPHRASE_SIZE
) {
421 printf("Passphrase size is %zd; max is %d.\n", passphrase_size
,
422 EXT4_MAX_PASSPHRASE_SIZE
);
425 if (salt
->salt_len
> EXT4_MAX_SALT_SIZE
) {
426 printf("Salt size is %zd; max is %d.\n", salt
->salt_len
,
430 assert(EXT4_MAX_KEY_SIZE
<= SHA512_LENGTH
);
432 memcpy(saltbuf
, salt
->salt
, salt
->salt_len
);
433 memcpy(&saltbuf
[EXT4_MAX_SALT_SIZE
], passphrase
, passphrase_size
);
435 memcpy(&buf
[SHA512_LENGTH
], passphrase
, passphrase_size
);
437 for (x
= 0; x
< count
; ++x
) {
439 ext2fs_sha512(saltbuf
, actual_saltbuf_len
, tempbuf
);
442 * buf: [previous hash || passphrase]
444 memcpy(buf
, tempbuf
, SHA512_LENGTH
);
445 ext2fs_sha512(buf
, actual_buf_len
, tempbuf
);
447 for (y
= 0; y
< (sizeof(final
) / sizeof(*final_u32
)); ++y
)
448 final_u32
[y
] = final_u32
[y
] ^ temp_u32
[y
];
450 memcpy(derived_key
, final
, EXT4_MAX_KEY_SIZE
);
453 static int disable_echo(struct termios
*saved_settings
)
455 struct termios current_settings
;
458 rc
= tcgetattr(0, ¤t_settings
);
461 *saved_settings
= current_settings
;
462 current_settings
.c_lflag
&= ~ECHO
;
463 rc
= tcsetattr(0, TCSANOW
, ¤t_settings
);
468 static void get_passphrase(char *passphrase
, int len
)
471 struct termios current_settings
;
474 disable_echo(¤t_settings
);
475 p
= fgets(passphrase
, len
, stdin
);
476 tcsetattr(0, TCSANOW
, ¤t_settings
);
479 printf("Aborting.\n");
482 p
= strrchr(passphrase
, '\n');
484 p
= passphrase
+ len
- 1;
494 static const struct keyring_map keyrings
[] = {
495 {"@us", 3, KEY_SPEC_USER_SESSION_KEYRING
},
496 {"@u", 2, KEY_SPEC_USER_KEYRING
},
497 {"@s", 2, KEY_SPEC_SESSION_KEYRING
},
498 {"@g", 2, KEY_SPEC_GROUP_KEYRING
},
499 {"@p", 2, KEY_SPEC_PROCESS_KEYRING
},
500 {"@t", 2, KEY_SPEC_THREAD_KEYRING
},
503 static int get_keyring_id(const char *keyring
)
509 * If no keyring is specified, by default use either the user
510 * session keyring or the session keyring. Fetching the
511 * session keyring will return the user session keyring if no
512 * session keyring has been set.
515 return KEY_SPEC_SESSION_KEYRING
;
516 for (x
= 0; x
< (sizeof(keyrings
) / sizeof(keyrings
[0])); ++x
) {
517 if (strcmp(keyring
, keyrings
[x
].name
) == 0) {
518 return keyrings
[x
].code
;
521 x
= strtoul(keyring
, &end
, 10);
523 if (keyctl(KEYCTL_DESCRIBE
, x
, NULL
, 0) < 0)
530 static void generate_key_ref_str(struct salt
*salt
)
532 unsigned char key_ref1
[SHA512_LENGTH
];
533 unsigned char key_ref2
[SHA512_LENGTH
];
536 ext2fs_sha512(salt
->key
, EXT4_MAX_KEY_SIZE
, key_ref1
);
537 ext2fs_sha512(key_ref1
, SHA512_LENGTH
, key_ref2
);
538 memcpy(salt
->key_desc
, key_ref2
, EXT4_KEY_DESCRIPTOR_SIZE
);
539 for (x
= 0; x
< EXT4_KEY_DESCRIPTOR_SIZE
; ++x
) {
540 sprintf(&salt
->key_ref_str
[x
* 2], "%02x",
543 salt
->key_ref_str
[EXT4_KEY_REF_STR_BUF_SIZE
- 1] = '\0';
546 static void insert_key_into_keyring(const char *keyring
, struct salt
*salt
)
548 int keyring_id
= get_keyring_id(keyring
);
549 struct ext4_encryption_key key
;
550 char key_ref_full
[EXT2FS_KEY_DESC_PREFIX_SIZE
+
551 EXT4_KEY_REF_STR_BUF_SIZE
];
554 if (keyring_id
== 0) {
555 printf("Invalid keyring [%s].\n", keyring
);
558 sprintf(key_ref_full
, "%s%s", EXT2FS_KEY_DESC_PREFIX
,
560 rc
= keyctl(KEYCTL_SEARCH
, keyring_id
, EXT2FS_KEY_TYPE_LOGON
,
563 if ((options
& OPT_QUIET
) == 0)
564 printf("Key with descriptor [%s] already exists\n",
567 } else if ((rc
== -1) && (errno
!= ENOKEY
)) {
568 printf("keyctl_search failed: %s\n", strerror(errno
));
569 if (errno
== -EINVAL
)
570 printf("Keyring [%s] is not available.\n", keyring
);
573 key
.mode
= EXT4_ENCRYPTION_MODE_AES_256_XTS
;
574 memcpy(key
.raw
, salt
->key
, EXT4_MAX_KEY_SIZE
);
575 key
.size
= EXT4_MAX_KEY_SIZE
;
578 * We need to do this instead of simply adding the key to
579 * KEY_SPEC_SESSION_KEYRING since trying to add a key to a
580 * session keyring that does not yet exist will cause the
581 * kernel to create a session keyring --- which will then get
582 * garbage collected as soon as e4crypt exits.
584 * The fact that the keyctl system call and the add_key system
585 * call treats KEY_SPEC_SESSION_KEYRING differently when a
586 * session keyring does not exist is very unfortunate and
587 * confusing, but so it goes...
589 if (keyring_id
== KEY_SPEC_SESSION_KEYRING
) {
590 keyring_id
= keyctl(KEYCTL_GET_KEYRING_ID
, keyring_id
, 0);
591 if (keyring_id
< 0) {
592 printf("Error getting session keyring ID: %s\n",
597 rc
= add_key(EXT2FS_KEY_TYPE_LOGON
, key_ref_full
, (void *)&key
,
598 sizeof(key
), keyring_id
);
600 if (errno
== EDQUOT
) {
601 printf("Error adding key to keyring; quota exceeded\n");
603 printf("Error adding key with key descriptor [%s]: "
604 "%s\n", salt
->key_ref_str
, strerror(errno
));
608 if ((options
& OPT_QUIET
) == 0)
609 printf("Added key with descriptor [%s]\n",
614 static void get_default_salts(void)
616 FILE *f
= setmntent("/etc/mtab", "r");
619 while (f
&& ((mnt
= getmntent(f
)) != NULL
)) {
620 if (strcmp(mnt
->mnt_type
, "ext4") ||
621 access(mnt
->mnt_dir
, R_OK
))
623 parse_salt(mnt
->mnt_dir
, PARSE_FLAGS_NOTSUPP_OK
);
628 /* Functions which implement user commands */
631 const char *cmd_name
;
632 void (*cmd_func
)(int, char **, const struct cmd_desc
*);
633 const char *cmd_desc
;
634 const char *cmd_help
;
638 #define CMD_HIDDEN 0x0001
640 static void do_help(int argc
, char **argv
, const struct cmd_desc
*cmd
);
642 #define add_key_desc "adds a key to the user's keyring"
643 #define add_key_help \
644 "e4crypt add_key -S salt [ -k keyring ] [-v] [-q] [ path ... ]\n\n" \
645 "Prompts the user for a passphrase and inserts it into the specified\n" \
646 "keyring. If no keyring is specified, e4crypt will use the session\n" \
647 "keyring if it exists or the user session keyring if it does not.\n\n" \
648 "If one or more directory paths are specified, e4crypt will try to\n" \
649 "set the policy of those directories to use the key just entered by\n" \
652 static void do_add_key(int argc
, char **argv
, const struct cmd_desc
*cmd
)
655 char *keyring
= NULL
;
659 while ((opt
= getopt(argc
, argv
, "k:S:p:vq")) != -1) {
662 /* Specify a keyring. */
669 /* Salt value for passphrase. */
670 parse_salt(optarg
, 0);
673 options
|= OPT_VERBOSE
;
676 options
|= OPT_QUIET
;
679 fprintf(stderr
, "Unrecognized option: %c\n", opt
);
681 fputs("USAGE:\n ", stderr
);
682 fputs(cmd
->cmd_help
, stderr
);
689 fprintf(stderr
, "No salt values available\n");
692 validate_paths(argc
, argv
, optind
);
693 for (i
= optind
; i
< argc
; i
++)
694 parse_salt(argv
[i
], PARSE_FLAGS_FORCE_FN
);
695 printf("Enter passphrase (echo disabled): ");
696 get_passphrase(in_passphrase
, sizeof(in_passphrase
));
697 for (j
= 0, salt
= salt_list
; j
< num_salt
; j
++, salt
++) {
698 pbkdf2_sha512(in_passphrase
, salt
,
699 EXT4_PBKDF2_ITERATIONS
, salt
->key
);
700 generate_key_ref_str(salt
);
701 insert_key_into_keyring(keyring
, salt
);
704 set_policy(NULL
, pad
, argc
, argv
, optind
);
709 #define set_policy_desc "sets a policy for directories"
710 #define set_policy_help \
711 "e4crypt set_policy policy path ... \n\n" \
712 "Sets the policy for the directories specified on the command line.\n" \
713 "All directories must be empty to set the policy; if the directory\n" \
714 "already has a policy established, e4crypt will validate that it the\n" \
715 "policy matches what was specified. A policy is an encryption key\n" \
716 "identifier consisting of 16 hexadecimal characters.\n"
718 static void do_set_policy(int argc
, char **argv
, const struct cmd_desc
*cmd
)
723 while ((c
= getopt (argc
, argv
, "p:")) != EOF
) {
731 if (argc
< optind
+ 2) {
732 fprintf(stderr
, "Missing required argument(s).\n\n");
733 fputs("USAGE:\n ", stderr
);
734 fputs(cmd
->cmd_help
, stderr
);
738 if ((strlen(argv
[optind
]) != (EXT4_KEY_DESCRIPTOR_SIZE
* 2)) ||
739 hex2byte(argv
[optind
], (EXT4_KEY_DESCRIPTOR_SIZE
* 2),
740 saltbuf
.key_desc
, EXT4_KEY_DESCRIPTOR_SIZE
)) {
741 printf("Invalid key descriptor [%s]. Valid characters "
742 "are 0-9 and a-f, lower case. "
743 "Length must be %d.\n",
744 argv
[optind
], (EXT4_KEY_DESCRIPTOR_SIZE
* 2));
747 validate_paths(argc
, argv
, optind
+1);
748 strcpy(saltbuf
.key_ref_str
, argv
[optind
]);
749 set_policy(&saltbuf
, pad
, argc
, argv
, optind
+1);
753 #define get_policy_desc "get the encryption for directories"
754 #define get_policy_help \
755 "e4crypt get_policy path ... \n\n" \
756 "Gets the policy for the directories specified on the command line.\n"
758 static void do_get_policy(int argc
, char **argv
, const struct cmd_desc
*cmd
)
760 struct ext4_encryption_policy policy
;
765 fprintf(stderr
, "Missing required argument(s).\n\n");
766 fputs("USAGE:\n ", stderr
);
767 fputs(cmd
->cmd_help
, stderr
);
771 for (i
= 1; i
< argc
; i
++) {
772 if (stat(argv
[i
], &st
) < 0) {
777 S_ISDIR(st
.st_mode
) ? O_DIRECTORY
: O_RDONLY
);
782 rc
= ioctl(fd
, EXT4_IOC_GET_ENCRYPTION_POLICY
, &policy
);
785 printf("Error getting policy for %s: %s\n",
786 argv
[i
], strerror(errno
));
789 printf("%s: ", argv
[i
]);
790 for (j
= 0; j
< EXT4_KEY_DESCRIPTOR_SIZE
; j
++) {
791 printf("%02x", (unsigned char) policy
.master_key_descriptor
[j
]);
798 #define new_session_desc "give the invoking process a new session keyring"
799 #define new_session_help \
800 "e4crypt new_session\n\n" \
801 "Give the invoking process (typically a shell) a new session keyring,\n" \
802 "discarding its old session keyring.\n"
804 static void do_new_session(int argc
, char **argv
EXT2FS_ATTR((unused
)),
805 const struct cmd_desc
*cmd
)
810 fputs("Excess arguments\n\n", stderr
);
811 fputs(cmd
->cmd_help
, stderr
);
814 keyid
= keyctl(KEYCTL_JOIN_SESSION_KEYRING
, NULL
);
816 perror("KEYCTL_JOIN_SESSION_KEYRING");
819 ret
= keyctl(KEYCTL_SESSION_TO_PARENT
, NULL
);
821 perror("KEYCTL_SESSION_TO_PARENT");
824 printf("Switched invoking process to new session keyring %ld\n", keyid
);
828 #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
829 #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
831 const struct cmd_desc cmd_list
[] = {
837 { NULL
, NULL
, NULL
, NULL
, 0 }
840 static void do_help(int argc
, char **argv
,
841 const struct cmd_desc
*cmd
EXT2FS_ATTR((unused
)))
843 const struct cmd_desc
*p
;
846 for (p
= cmd_list
; p
->cmd_name
; p
++) {
847 if (p
->cmd_flags
& CMD_HIDDEN
)
849 if (strcmp(p
->cmd_name
, argv
[1]) == 0) {
851 fputs("USAGE:\n ", stdout
);
852 fputs(p
->cmd_help
, stdout
);
856 printf("Unknown command: %s\n\n", argv
[1]);
859 fputs("Available commands:\n", stdout
);
860 for (p
= cmd_list
; p
->cmd_name
; p
++) {
861 if (p
->cmd_flags
& CMD_HIDDEN
)
863 printf(" %-20s %s\n", p
->cmd_name
, p
->cmd_desc
);
865 printf("\nTo get more information on a command, "
866 "type 'e4crypt help cmd'\n");
870 int main(int argc
, char *argv
[])
872 const struct cmd_desc
*cmd
;
875 do_help(argc
, argv
, cmd_list
);
878 for (cmd
= cmd_list
; cmd
->cmd_name
; cmd
++) {
879 if (strcmp(cmd
->cmd_name
, argv
[1]) == 0) {
880 cmd
->cmd_func(argc
-1, argv
+1, cmd
);
884 printf("Unknown command: %s\n\n", argv
[1]);
885 do_help(1, argv
, cmd_list
);