/
githubmirror
/
keyutils
Обзор
Документация
Войти
/
githubmirror
/
keyutils
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v1.3
keyctl.c
1 402 строки
30 KB
David Howells
Add keyctl command to give the parent process a new keyring
26 фев 2010, 23:28
26 фев 2010, 23:28
79f87dc
Код
Авторство
О чём код?
/* keyctl.c: key control program * * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdarg.h> #include <string.h> #include <unistd.h> #include <ctype.h> #include <errno.h> #include <asm/unistd.h> #include "keyutils.h" struct command { int (*action)(int argc, char *argv[]); const char *name; const char *format; }; static int act_keyctl_show(int argc, char *argv[]); static int act_keyctl_add(int argc, char *argv[]); static int act_keyctl_padd(int argc, char *argv[]); static int act_keyctl_request(int argc, char *argv[]); static int act_keyctl_request2(int argc, char *argv[]); static int act_keyctl_prequest2(int argc, char *argv[]); static int act_keyctl_update(int argc, char *argv[]); static int act_keyctl_pupdate(int argc, char *argv[]); static int act_keyctl_newring(int argc, char *argv[]); static int act_keyctl_revoke(int argc, char *argv[]); static int act_keyctl_clear(int argc, char *argv[]); static int act_keyctl_link(int argc, char *argv[]); static int act_keyctl_unlink(int argc, char *argv[]); static int act_keyctl_search(int argc, char *argv[]); static int act_keyctl_read(int argc, char *argv[]); static int act_keyctl_pipe(int argc, char *argv[]); static int act_keyctl_print(int argc, char *argv[]); static int act_keyctl_list(int argc, char *argv[]); static int act_keyctl_rlist(int argc, char *argv[]); static int act_keyctl_describe(int argc, char *argv[]); static int act_keyctl_rdescribe(int argc, char *argv[]); static int act_keyctl_chown(int argc, char *argv[]); static int act_keyctl_chgrp(int argc, char *argv[]); static int act_keyctl_setperm(int argc, char *argv[]); static int act_keyctl_session(int argc, char *argv[]); static int act_keyctl_instantiate(int argc, char *argv[]); static int act_keyctl_pinstantiate(int argc, char *argv[]); static int act_keyctl_negate(int argc, char *argv[]); static int act_keyctl_timeout(int argc, char *argv[]); static int act_keyctl_security(int argc, char *argv[]); static int act_keyctl_new_session(int argc, char *argv[]); const struct command commands[] = { { act_keyctl_show, "show", "" }, { act_keyctl_add, "add", "<type> <desc> <data> <keyring>" }, { act_keyctl_padd, "padd", "<type> <desc> <keyring>" }, { act_keyctl_request, "request", "<type> <desc> [<dest_keyring>]" }, { act_keyctl_request2, "request2", "<type> <desc> <info> [<dest_keyring>]" }, { act_keyctl_prequest2, "prequest2", "<type> <desc> [<dest_keyring>]" }, { act_keyctl_update, "update", "<key> <data>" }, { act_keyctl_pupdate, "pupdate", "<key>" }, { act_keyctl_newring, "newring", "<name> <keyring>" }, { act_keyctl_revoke, "revoke", "<key>" }, { act_keyctl_clear, "clear", "<keyring>" }, { act_keyctl_link, "link", "<key> <keyring>" }, { act_keyctl_unlink, "unlink", "<key> <keyring>" }, { act_keyctl_search, "search", "<keyring> <type> <desc> [<dest_keyring>]" }, { act_keyctl_read, "read", "<key>" }, { act_keyctl_pipe, "pipe", "<key>" }, { act_keyctl_print, "print", "<key>" }, { act_keyctl_list, "list", "<keyring>" }, { act_keyctl_rlist, "rlist", "<keyring>" }, { act_keyctl_describe, "describe", "<keyring>" }, { act_keyctl_rdescribe, "rdescribe", "<keyring> [sep]" }, { act_keyctl_chown, "chown", "<key> <uid>" }, { act_keyctl_chgrp, "chgrp", "<key> <gid>" }, { act_keyctl_setperm, "setperm", "<key> <mask>" }, { act_keyctl_session, "session", "" }, { act_keyctl_session, "session", "- [<prog> <arg1> <arg2> ...]" }, { act_keyctl_session, "session", "<name> [<prog> <arg1> <arg2> ...]" }, { act_keyctl_instantiate, "instantiate","<key> <data> <keyring>" }, { act_keyctl_pinstantiate, "pinstantiate","<key> <keyring>" }, { act_keyctl_negate, "negate", "<key> <timeout> <keyring>" }, { act_keyctl_timeout, "timeout", "<key> <timeout>" }, { act_keyctl_security, "security", "<key>" }, { act_keyctl_new_session, "new_session", "" }, { NULL, NULL, NULL } }; static int dump_key_tree(key_serial_t keyring, const char *name); static void format(void) __attribute__((noreturn)); static void error(const char *msg) __attribute__((noreturn)); static key_serial_t get_key_id(const char *arg); static uid_t myuid; static gid_t mygid, *mygroups; static int myngroups; /*****************************************************************************/ /* * handle an error */ static inline void error(const char *msg) { perror(msg); exit(1); } /* end error() */ /*****************************************************************************/ /* * execute the appropriate subcommand */ int main(int argc, char *argv[]) { const struct command *cmd, *best; int n; argv++; argc--; if (argc == 0) format(); /* find the best fit command */ best = NULL; n = strlen(*argv); for (cmd = commands; cmd->action; cmd++) { if (memcmp(cmd->name, *argv, n) != 0) continue; if (cmd->name[n] == 0) { /* exact match */ best = cmd; break; } /* partial match */ if (best) { fprintf(stderr, "Ambiguous command\n"); exit(2); } best = cmd; } if (!best) { fprintf(stderr, "Unknown command\n"); exit(2); } /* grab my UID, GID and groups */ myuid = geteuid(); mygid = getegid(); myngroups = getgroups(0, NULL); if (myuid == -1 || mygid == -1 || myngroups == -1) error("Unable to get UID/GID/#Groups\n"); mygroups = calloc(myngroups, sizeof(gid_t)); if (!mygroups) error("calloc"); myngroups = getgroups(myngroups, mygroups); if (myngroups < 0) error("Unable to get Groups\n"); return best->action(argc, argv); } /* end main() */ /*****************************************************************************/ /* * display command format information */ static void format(void) { const struct command *cmd; fprintf(stderr, "Format:\n"); for (cmd = commands; cmd->action; cmd++) fprintf(stderr, " keyctl %s %s\n", cmd->name, cmd->format); fprintf(stderr, "\n"); fprintf(stderr, "Key/keyring ID:\n"); fprintf(stderr, " <nnn> numeric keyring ID\n"); fprintf(stderr, " @t thread keyring\n"); fprintf(stderr, " @p process keyring\n"); fprintf(stderr, " @s session keyring\n"); fprintf(stderr, " @u user keyring\n"); fprintf(stderr, " @us user default session keyring\n"); fprintf(stderr, " @g group keyring\n"); fprintf(stderr, " @a assumed request_key authorisation key\n"); fprintf(stderr, "\n"); fprintf(stderr, "<type> can be \"user\" for a user-defined keyring\n"); fprintf(stderr, "If you do this, prefix the description with \"<subtype>:\"\n"); exit(2); } /* end format() */ /*****************************************************************************/ /* * grab data from stdin */ static char *grab_stdin(void) { static char input[65536 + 1]; int n, tmp; n = 0; do { tmp = read(0, input + n, sizeof(input) - 1 - n); if (tmp < 0) error("stdin"); if (tmp == 0) break; n += tmp; } while (n < sizeof(input)); if (n >= sizeof(input)) { fprintf(stderr, "Too much data read on stdin\n"); exit(1); } input[n] = '\0'; return input; } /* end grab_stdin() */ /*****************************************************************************/ /* * convert the permissions mask to a string representing the permissions we * have actually been granted */ static void calc_perms(char *pretty, key_perm_t perm, uid_t uid, gid_t gid) { unsigned perms; gid_t *pg; int loop; perms = (perm & KEY_POS_ALL) >> 24; if (uid == myuid) { perms |= (perm & KEY_USR_ALL) >> 16; goto write_mask; } if (gid != -1) { if (gid == mygid) { perms |= (perm & KEY_GRP_ALL) >> 8; goto write_mask; } pg = mygroups; for (loop = myngroups; loop > 0; loop--, pg++) { if (gid == *pg) { perms |= (perm & KEY_GRP_ALL) >> 8; goto write_mask; } } } perms |= (perm & KEY_OTH_ALL); write_mask: sprintf(pretty, "--%c%c%c%c%c%c", perms & KEY_OTH_SETATTR ? 'a' : '-', perms & KEY_OTH_LINK ? 'l' : '-', perms & KEY_OTH_SEARCH ? 's' : '-', perms & KEY_OTH_WRITE ? 'w' : '-', perms & KEY_OTH_READ ? 'r' : '-', perms & KEY_OTH_VIEW ? 'v' : '-'); } /* end calc_perms() */ /*****************************************************************************/ /* * show the parent process's session keyring */ static int act_keyctl_show(int argc, char *argv[]) { if (argc != 1) format(); dump_key_tree(KEY_SPEC_SESSION_KEYRING, "Session Keyring"); return 0; } /* end act_keyctl_show() */ /*****************************************************************************/ /* * add a key */ static int act_keyctl_add(int argc, char *argv[]) { key_serial_t dest; int ret; if (argc != 5) format(); dest = get_key_id(argv[4]); ret = add_key(argv[1], argv[2], argv[3], strlen(argv[3]), dest); if (ret < 0) error("add_key"); /* print the resulting key ID */ printf("%d\n", ret); return 0; } /* end act_keyctl_add() */ /*****************************************************************************/ /* * add a key, reading from a pipe */ static int act_keyctl_padd(int argc, char *argv[]) { char *args[6]; if (argc != 4) format(); args[0] = argv[0]; args[1] = argv[1]; args[2] = argv[2]; args[3] = grab_stdin(); args[4] = argv[3]; args[5] = NULL; return act_keyctl_add(5, args); } /* end act_keyctl_padd() */ /*****************************************************************************/ /* * request a key */ static int act_keyctl_request(int argc, char *argv[]) { key_serial_t dest; int ret; if (argc != 3 && argc != 4) format(); dest = 0; if (argc == 4) dest = get_key_id(argv[3]); ret = request_key(argv[1], argv[2], NULL, dest); if (ret < 0) error("request_key"); /* print the resulting key ID */ printf("%d\n", ret); return 0; } /* end act_keyctl_request() */ /*****************************************************************************/ /* * request a key, with recourse to /sbin/request-key */ static int act_keyctl_request2(int argc, char *argv[]) { key_serial_t dest; int ret; if (argc != 4 && argc != 5) format(); dest = 0; if (argc == 5) dest = get_key_id(argv[4]); ret = request_key(argv[1], argv[2], argv[3], dest); if (ret < 0) error("request_key"); /* print the resulting key ID */ printf("%d\n", ret); return 0; } /* end act_keyctl_request2() */ /*****************************************************************************/ /* * request a key, with recourse to /sbin/request-key, reading the callout info * from a pipe */ static int act_keyctl_prequest2(int argc, char *argv[]) { char *args[6]; if (argc != 3 && argc != 4) format(); args[0] = argv[0]; args[1] = argv[1]; args[2] = argv[2]; args[3] = grab_stdin(); args[4] = argv[3]; args[5] = NULL; return act_keyctl_request2(argc + 1, args); } /* end act_keyctl_prequest2() */ /*****************************************************************************/ /* * update a key */ static int act_keyctl_update(int argc, char *argv[]) { key_serial_t key; if (argc != 3) format(); key = get_key_id(argv[1]); if (keyctl_update(key, argv[2], strlen(argv[2])) < 0) error("keyctl_update"); return 0; } /* end act_keyctl_update() */ /*****************************************************************************/ /* * update a key, reading from a pipe */ static int act_keyctl_pupdate(int argc, char *argv[]) { char *args[4]; if (argc != 2) format(); args[0] = argv[0]; args[1] = argv[1]; args[2] = grab_stdin(); args[3] = NULL; return act_keyctl_update(3, args); } /* end act_keyctl_pupdate() */ /*****************************************************************************/ /* * create a new keyring */ static int act_keyctl_newring(int argc, char *argv[]) { key_serial_t dest; int ret; if (argc != 3) format(); dest = get_key_id(argv[2]); ret = add_key("keyring", argv[1], NULL, 0, dest); if (ret < 0) error("add_key"); printf("%d\n", ret); return 0; } /* end act_keyctl_newring() */ /*****************************************************************************/ /* * revoke a key */ static int act_keyctl_revoke(int argc, char *argv[]) { key_serial_t key; if (argc != 2) format(); key = get_key_id(argv[1]); if (keyctl_revoke(key) < 0) error("keyctl_revoke"); return 0; } /* end act_keyctl_revoke() */ /*****************************************************************************/ /* * clear a keyring */ static int act_keyctl_clear(int argc, char *argv[]) { key_serial_t keyring; if (argc != 2) format(); keyring = get_key_id(argv[1]); if (keyctl_clear(keyring) < 0) error("keyctl_clear"); return 0; } /* end act_keyctl_clear() */ /*****************************************************************************/ /* * link a key to a keyring */ static int act_keyctl_link(int argc, char *argv[]) { key_serial_t keyring, key; if (argc != 3) format(); key = get_key_id(argv[1]); keyring = get_key_id(argv[2]); if (keyctl_link(key, keyring) < 0) error("keyctl_link"); return 0; } /* end act_keyctl_link() */ /*****************************************************************************/ /* * unlink a key from a keyrign */ static int act_keyctl_unlink(int argc, char *argv[]) { key_serial_t keyring, key; if (argc != 3) format(); key = get_key_id(argv[1]); keyring = get_key_id(argv[2]); if (keyctl_unlink(key, keyring) < 0) error("keyctl_unlink"); return 0; } /* end act_keyctl_unlink() */ /*****************************************************************************/ /* * search a keyring for a key */ static int act_keyctl_search(int argc, char *argv[]) { key_serial_t keyring, dest; int ret; if (argc != 4 && argc != 5) format(); keyring = get_key_id(argv[1]); dest = 0; if (argc == 5) dest = get_key_id(argv[4]); ret = keyctl_search(keyring, argv[2], argv[3], dest); if (ret < 0) error("keyctl_search"); /* print the ID of the key we found */ printf("%d\n", ret); return 0; } /* end act_keyctl_search() */ /*****************************************************************************/ /* * read a key */ static int act_keyctl_read(int argc, char *argv[]) { key_serial_t key; void *buffer; char *p; int ret, sep, col; if (argc != 2) format(); key = get_key_id(argv[1]); /* read the key payload data */ ret = keyctl_read_alloc(key, &buffer); if (ret < 0) error("keyctl_read_alloc"); if (ret == 0) { printf("No data in key\n"); return 0; } /* hexdump the contents */ printf("%u bytes of data in key:\n", ret); sep = 0; col = 0; p = buffer; do { if (sep) { putchar(sep); sep = 0; } printf("%02hhx", *p); p++; col++; if (col % 32 == 0) sep = '\n'; else if (col % 4 == 0) sep = ' '; } while (--ret > 0); printf("\n"); return 0; } /* end act_keyctl_read() */ /*****************************************************************************/ /* * read a key and dump raw to stdout */ static int act_keyctl_pipe(int argc, char *argv[]) { key_serial_t key; void *buffer; int ret; if (argc != 2) format(); key = get_key_id(argv[1]); /* read the key payload data */ ret = keyctl_read_alloc(key, &buffer); if (ret < 0) error("keyctl_read_alloc"); if (ret > 0 && write(1, buffer, ret) < 0) error("write"); return 0; } /* end act_keyctl_pipe() */ /*****************************************************************************/ /* * read a key and dump to stdout in printable form */ static int act_keyctl_print(int argc, char *argv[]) { key_serial_t key; void *buffer; char *p; int loop, ret; if (argc != 2) format(); key = get_key_id(argv[1]); /* read the key payload data */ ret = keyctl_read_alloc(key, &buffer); if (ret < 0) error("keyctl_read_alloc"); /* see if it's printable */ p = buffer; for (loop = ret; loop > 0; loop--, p++) if (!isprint(*p)) goto not_printable; /* it is */ printf("%s\n", (char *) buffer); return 0; not_printable: /* it isn't */ printf(":hex:"); p = buffer; for (loop = ret; loop > 0; loop--, p++) printf("%02hhx", *p); printf("\n"); return 0; } /* end act_keyctl_print() */ /*****************************************************************************/ /* * list a keyring */ static int act_keyctl_list(int argc, char *argv[]) { key_serial_t keyring, key, *pk; key_perm_t perm; void *keylist; char *buffer, pretty_mask[9]; uid_t uid; gid_t gid; int count, tlen, dpos, n, ret; if (argc != 2) format(); keyring = get_key_id(argv[1]); /* read the key payload data */ count = keyctl_read_alloc(keyring, &keylist); if (count < 0) error("keyctl_read_alloc"); count /= sizeof(key_serial_t); if (count == 0) { printf("keyring is empty\n"); return 0; } /* list the keys in the keyring */ if (count == 1) printf("1 key in keyring:\n"); else printf("%u keys in keyring:\n", count); pk = keylist; do { key = *pk++; ret = keyctl_describe_alloc(key, &buffer); if (ret < 0) { printf("%9d: key inaccessible (%m)\n", key); continue; } uid = 0; gid = 0; perm = 0; tlen = -1; dpos = -1; n = sscanf((char *) buffer, "%*[^;]%n;%d;%d;%x;%n", &tlen, &uid, &gid, &perm, &dpos); if (n != 3) { fprintf(stderr, "Unparseable description obtained for key %d\n", key); exit(3); } calc_perms(pretty_mask, perm, uid, gid); printf("%9d: %s %5d %5d %*.*s: %s\n", key, pretty_mask, uid, gid, tlen, tlen, buffer, buffer + dpos); free(buffer); } while (--count); return 0; } /* end act_keyctl_list() */ /*****************************************************************************/ /* * produce a raw list of a keyring */ static int act_keyctl_rlist(int argc, char *argv[]) { key_serial_t keyring, key, *pk; void *keylist; int count; if (argc != 2) format(); keyring = get_key_id(argv[1]); /* read the key payload data */ count = keyctl_read_alloc(keyring, &keylist); if (count < 0) error("keyctl_read_alloc"); count /= sizeof(key_serial_t); /* list the keys in the keyring */ if (count <= 0) { printf("\n"); } else { pk = keylist; for (; count > 0; count--) { key = *pk++; printf("%d%c", key, count == 1 ? '\n' : ' '); } } return 0; } /* end act_keyctl_rlist() */ /*****************************************************************************/ /* * describe a key */ static int act_keyctl_describe(int argc, char *argv[]) { key_serial_t key; key_perm_t perm; char *buffer; uid_t uid; gid_t gid; int tlen, dpos, n, ret; if (argc != 2) format(); key = get_key_id(argv[1]); /* get key description */ ret = keyctl_describe_alloc(key, &buffer); if (ret < 0) error("keyctl_describe"); /* parse it */ uid = 0; gid = 0; perm = 0; tlen = -1; dpos = -1; n = sscanf(buffer, "%*[^;]%n;%d;%d;%x;%n", &tlen, &uid, &gid, &perm, &dpos); if (n != 3) { fprintf(stderr, "Unparseable description obtained for key %d\n", key); exit(3); } /* display it */ printf("%9d:" " %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c" " %5d %5d %*.*s: %s\n", key, perm & KEY_POS_SETATTR ? 'a' : '-', perm & KEY_POS_LINK ? 'l' : '-', perm & KEY_POS_SEARCH ? 's' : '-', perm & KEY_POS_WRITE ? 'w' : '-', perm & KEY_POS_READ ? 'r' : '-', perm & KEY_POS_VIEW ? 'v' : '-', perm & KEY_USR_SETATTR ? 'a' : '-', perm & KEY_USR_LINK ? 'l' : '-', perm & KEY_USR_SEARCH ? 's' : '-', perm & KEY_USR_WRITE ? 'w' : '-', perm & KEY_USR_READ ? 'r' : '-', perm & KEY_USR_VIEW ? 'v' : '-', perm & KEY_GRP_SETATTR ? 'a' : '-', perm & KEY_GRP_LINK ? 'l' : '-', perm & KEY_GRP_SEARCH ? 's' : '-', perm & KEY_GRP_WRITE ? 'w' : '-', perm & KEY_GRP_READ ? 'r' : '-', perm & KEY_GRP_VIEW ? 'v' : '-', perm & KEY_OTH_SETATTR ? 'a' : '-', perm & KEY_OTH_LINK ? 'l' : '-', perm & KEY_OTH_SEARCH ? 's' : '-', perm & KEY_OTH_WRITE ? 'w' : '-', perm & KEY_OTH_READ ? 'r' : '-', perm & KEY_OTH_VIEW ? 'v' : '-', uid, gid, tlen, tlen, buffer, buffer + dpos); return 0; } /* end act_keyctl_describe() */ /*****************************************************************************/ /* * get raw key description */ static int act_keyctl_rdescribe(int argc, char *argv[]) { key_serial_t key; char *buffer, *q; int ret; if (argc != 2 && argc != 3) format(); if (argc == 3 && !argv[2][0]) format(); key = get_key_id(argv[1]); /* get key description */ ret = keyctl_describe_alloc(key, &buffer); if (ret < 0) error("keyctl_describe"); /* replace semicolon separators with requested alternative */ if (argc == 3) { for (q = buffer; *q; q++) if (*q == ';') *q = argv[2][0]; } /* display raw description */ printf("%s\n", buffer); return 0; } /* end act_keyctl_rdescribe() */ /*****************************************************************************/ /* * change a key's ownership */ static int act_keyctl_chown(int argc, char *argv[]) { key_serial_t key; uid_t uid; char *q; if (argc != 3) format(); key = get_key_id(argv[1]); uid = strtoul(argv[2], &q, 0); if (*q) { fprintf(stderr, "Unparsable uid: '%s'\n", argv[2]); exit(2); } if (keyctl_chown(key, uid, -1) < 0) error("keyctl_chown"); return 0; } /* end act_keyctl_chown() */ /*****************************************************************************/ /* * change a key's group ownership */ static int act_keyctl_chgrp(int argc, char *argv[]) { key_serial_t key; gid_t gid; char *q; if (argc != 3) format(); key = get_key_id(argv[1]); gid = strtoul(argv[2], &q, 0); if (*q) { fprintf(stderr, "Unparsable gid: '%s'\n", argv[2]); exit(2); } if (keyctl_chown(key, -1, gid) < 0) error("keyctl_chown"); return 0; } /* end act_keyctl_chgrp() */ /*****************************************************************************/ /* * set the permissions on a key */ static int act_keyctl_setperm(int argc, char *argv[]) { key_serial_t key; key_perm_t perm; char *q; if (argc != 3) format(); key = get_key_id(argv[1]); perm = strtoul(argv[2], &q, 0); if (*q) { fprintf(stderr, "Unparsable permissions: '%s'\n", argv[2]); exit(2); } if (keyctl_setperm(key, perm) < 0) error("keyctl_setperm"); return 0; } /* end act_keyctl_setperm() */ /*****************************************************************************/ /* * start a process in a new session */ static int act_keyctl_session(int argc, char *argv[]) { char *p, *q; int ret; argv++; argc--; /* no extra arguments signifies a standard shell in an anonymous * session */ p = NULL; if (argc != 0) { /* a dash signifies an anonymous session */ p = *argv; if (strcmp(p, "-") == 0) p = NULL; argv++; argc--; } /* create a new session keyring */ ret = keyctl_join_session_keyring(p); if (ret < 0) error("keyctl_join_session_keyring"); fprintf(stderr, "Joined session keyring: %d\n", ret); /* run the standard shell if no arguments */ if (argc == 0) { q = getenv("SHELL"); if (!q) q = "/bin/sh"; execl(q, q, NULL); error(q); } /* run the command specified */ execvp(argv[0], argv); error(argv[0]); } /* end act_keyctl_session() */ /*****************************************************************************/ /* * instantiate a key that's under construction */ static int act_keyctl_instantiate(int argc, char *argv[]) { key_serial_t key, dest; if (argc != 4) format(); key = get_key_id(argv[1]); dest = get_key_id(argv[3]); if (keyctl_instantiate(key, argv[2], strlen(argv[2]), dest) < 0) error("keyctl_instantiate"); return 0; } /* end act_keyctl_instantiate() */ /*****************************************************************************/ /* * instantiate a key, reading from a pipe */ static int act_keyctl_pinstantiate(int argc, char *argv[]) { char *args[5]; if (argc != 3) format(); args[0] = argv[0]; args[1] = argv[1]; args[2] = grab_stdin(); args[3] = argv[2]; args[4] = NULL; return act_keyctl_instantiate(4, args); } /* end act_keyctl_pinstantiate() */ /*****************************************************************************/ /* * negate a key that's under construction */ static int act_keyctl_negate(int argc, char *argv[]) { unsigned long timeout; key_serial_t key, dest; char *q; if (argc != 4) format(); key = get_key_id(argv[1]); timeout = strtoul(argv[2], &q, 10); if (*q) { fprintf(stderr, "Unparsable timeout: '%s'\n", argv[2]); exit(2); } dest = get_key_id(argv[3]); if (keyctl_negate(key, timeout, dest) < 0) error("keyctl_negate"); return 0; } /* end act_keyctl_negate() */ /*****************************************************************************/ /* * set a key's timeout */ static int act_keyctl_timeout(int argc, char *argv[]) { unsigned long timeout; key_serial_t key; char *q; if (argc != 3) format(); key = get_key_id(argv[1]); timeout = strtoul(argv[2], &q, 10); if (*q) { fprintf(stderr, "Unparsable timeout: '%s'\n", argv[2]); exit(2); } if (keyctl_set_timeout(key, timeout) < 0) error("keyctl_set_timeout"); return 0; } /* end act_keyctl_timeout() */ /*****************************************************************************/ /* * get a key's security label */ static int act_keyctl_security(int argc, char *argv[]) { key_serial_t key; char *buffer; int ret; if (argc != 2) format(); key = get_key_id(argv[1]); /* get key description */ ret = keyctl_get_security_alloc(key, &buffer); if (ret < 0) error("keyctl_getsecurity"); printf("%s\n", buffer); return 0; } /*****************************************************************************/ /* * install a new session keyring on the parent process */ static int act_keyctl_new_session(int argc, char *argv[]) { key_serial_t keyring; if (argc != 1) format(); if (keyctl_join_session_keyring(NULL) < 0) error("keyctl_join_session_keyring"); if (keyctl_session_to_parent() < 0) error("keyctl_session_to_parent"); keyring = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); if (keyring < 0) error("keyctl_get_keyring_ID"); /* print the resulting key ID */ printf("%d\n", keyring); return 0; } /*****************************************************************************/ /* * parse a key identifier */ static key_serial_t get_key_id(const char *arg) { key_serial_t id; char *end; /* handle a special keyring name */ if (arg[0] == '@') { if (strcmp(arg, "@t" ) == 0) return KEY_SPEC_THREAD_KEYRING; if (strcmp(arg, "@p" ) == 0) return KEY_SPEC_PROCESS_KEYRING; if (strcmp(arg, "@s" ) == 0) return KEY_SPEC_SESSION_KEYRING; if (strcmp(arg, "@u" ) == 0) return KEY_SPEC_USER_KEYRING; if (strcmp(arg, "@us") == 0) return KEY_SPEC_USER_SESSION_KEYRING; if (strcmp(arg, "@g" ) == 0) return KEY_SPEC_GROUP_KEYRING; if (strcmp(arg, "@a" ) == 0) return KEY_SPEC_REQKEY_AUTH_KEY; fprintf(stderr, "Unknown special key: '%s'\n", arg); exit(2); } /* handle a numeric key ID */ id = strtoul(arg, &end, 0); if (*end) { fprintf(stderr, "Unparsable key: '%s'\n", arg); exit(2); } return id; } /* end get_key_id() */ /*****************************************************************************/ /* * recursively display a key/keyring tree */ static int dump_key_tree_aux(key_serial_t key, int depth, int more) { static char dumpindent[64]; key_serial_t *pk; key_perm_t perm; size_t ringlen, desclen; void *payload; char *desc, type[255], pretty_mask[9]; int uid, gid, ret, n, dpos, rdepth, kcount = 0; if (depth > 8) return 0; /* find out how big this key's description is */ ret = keyctl_describe(key, NULL, 0); if (ret < 0) { printf("%d: key inaccessible (%m)\n", key); return 0; } desclen = ret + 1; desc = malloc(desclen); if (!desc) error("malloc"); /* read the description */ ret = keyctl_describe(key, desc, desclen); if (ret < 0) { printf("%d: key inaccessible (%m)\n", key); free(desc); return 0; } desclen = ret < desclen ? ret : desclen; desc[desclen] = 0; /* parse */ type[0] = 0; uid = 0; gid = 0; perm = 0; n = sscanf(desc, "%[^;];%d;%d;%x;%n", type, &uid, &gid, &perm, &dpos); if (n != 4) { fprintf(stderr, "Unparseable description obtained for key %d\n", key); exit(3); } /* and print */ calc_perms(pretty_mask, perm, uid, gid); printf("%9d %s %5d %5d %s%s%s: %s\n", key, pretty_mask, uid, gid, dumpindent, depth > 0 ? "\\_ " : "", type, desc + dpos); /* if it's a keyring then we're going to want to recursively * display it if we can */ if (strcmp(type, "keyring") == 0) { /* find out how big the keyring is */ ret = keyctl_read(key, NULL, 0); if (ret < 0) error("keyctl_read"); if (ret == 0) return 0; ringlen = ret; /* read its contents */ payload = malloc(ringlen); if (!payload) error("malloc"); ret = keyctl_read(key, payload, ringlen); if (ret < 0) error("keyctl_read"); ringlen = ret < ringlen ? ret : ringlen; kcount = ringlen / sizeof(key_serial_t); /* walk the keyring */ pk = payload; do { key = *pk++; /* recurse into nexted keyrings */ if (strcmp(type, "keyring") == 0) { if (depth == 0) { rdepth = depth; dumpindent[rdepth++] = ' '; dumpindent[rdepth] = 0; } else { rdepth = depth; dumpindent[rdepth++] = ' '; dumpindent[rdepth++] = ' '; dumpindent[rdepth++] = ' '; dumpindent[rdepth++] = ' '; dumpindent[rdepth] = 0; } if (more) dumpindent[depth + 0] = '|'; kcount += dump_key_tree_aux(key, rdepth, ringlen - 4 >= sizeof(key_serial_t)); } } while (ringlen -= 4, ringlen >= sizeof(key_serial_t)); free(payload); } free(desc); return kcount; } /* end dump_key_tree_aux() */ /*****************************************************************************/ /* * recursively list a keyring's contents */ static int dump_key_tree(key_serial_t keyring, const char *name) { printf("%s\n", name); return dump_key_tree_aux(keyring, 0, 0); } /* end dump_key_tree() */