diff options
author | David Howells <dhowells@redhat.com> | 2013-09-10 18:38:02 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2013-10-02 15:58:10 +0100 |
commit | 949159b53e688f6daa0e10dd50058a2dd929234d (patch) | |
tree | 4775421c4979f9a55af097a1460e08d62f92f417 | |
parent | b59512468561ffc3f85d1e808b5d2ae6a6313276 (diff) | |
download | keyutils-949159b53e688f6daa0e10dd50058a2dd929234d.tar.gz |
Lib: Add a function to find a key by type and name, even if non-possessed
Add a function to find a key by its type and name, even if the key is not in
the process's thread, process or session keyrings (ie. it is not 'possessed'
by the process).
This looks in two places:
(1) Firstly, it looks in the processes attached keyrings so that possessed
keys are prioritised over non-possessed keys.
(2) Secondly, it scans /proc/keys, looking for a key matching the name. It
uses keyctl_describe() to check the name because the key description in
/proc/keys may have extra information appended by the type - but this
cannot be distinguished from keys that have stuff that looks like the
extra information embedded in the description.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | find_key_by_type_and_name.3 | 61 | ||||
-rw-r--r-- | keyctl.3 | 4 | ||||
-rw-r--r-- | keyutils.c | 83 | ||||
-rw-r--r-- | keyutils.h | 2 | ||||
-rw-r--r-- | version.lds | 1 |
5 files changed, 150 insertions, 1 deletions
diff --git a/find_key_by_type_and_name.3 b/find_key_by_type_and_name.3 new file mode 100644 index 0000000..c1db344 --- /dev/null +++ b/find_key_by_type_and_name.3 @@ -0,0 +1,61 @@ +.\" +.\" Copyright (C) 2013 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 Licence +.\" as published by the Free Software Foundation; either version +.\" 2 of the Licence, or (at your option) any later version. +.\" +.TH FIND_KEY_BY_TYPE_AND_NAME 3 "10 Sep 2013" Linux "Linux Key Utility Calls" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH NAME +find_key_by_type_and_name \- Find a key by type and name +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SYNOPSIS +.nf +.B #include <keyutils.h> +.sp +.BI "key_serial_t find_key_by_type_and_name(const char *" type , +.BI " const char *" description ", key_serial_t " destringid ");" +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH DESCRIPTION +.BR find_key_by_type_and_name () +searches for a key with the given +.I type +and exact +.IR description , +firstly in the thread, process and session keyrings to which a process is +subscribed and secondly in /proc/keys. +.P +If a key is found, and +.I destringid +is not 0 and specifies a keyring, then the found key will be linked into it. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH RETURN VALUE +The function returns the ID of the key if a key was found or -1 otherwise. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH ERRORS +.TP +.B ENOKEY +No key was found or the keyring specified is invalid. +.TP +.B EKEYEXPIRED +The key or keyring have expired. +.TP +.B EKEYREVOKED +The key or keyring have been revoked. +.TP +.B EACCES +The key is not accessible or keyring exists, but is not +.B writable +by the calling process. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH LINKING +When linking, +.B -lkeyutils +should be specified to the linker. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.SH SEE ALSO +.BR keyctl (3), +.BR request_key (3) @@ -7,7 +7,7 @@ .\" as published by the Free Software Foundation; either version .\" 2 of the Licence, or (at your option) any later version. .\" -.TH KEYCTL 3 "29 Aug 2013" Linux "Linux Key Management Calls" +.TH KEYCTL 3 "10 Sep 2013" Linux "Linux Key Management Calls" .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH NAME keyctl_*() \- Key management function wrappers @@ -82,6 +82,8 @@ and then telling the linker it should link in the library: .BR keyctl_update (3) .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .SH UTILITY FUNCTIONS +.BR find_key_by_type_and_name (3) +.br .BR recursive_key_scan (3) .br .BR recursive_session_key_scan (3) @@ -429,6 +429,89 @@ int recursive_session_key_scan(recursive_key_scanner_t func, void *data) return 0; } +/* + * Find a key by type and description + */ +key_serial_t find_key_by_type_and_desc(const char *type, const char *desc, + key_serial_t destringid) +{ + key_serial_t id, error; + FILE *f; + char buf[1024], typebuf[40], rdesc[1024], *kdesc, *cp; + int n, ndesc, dlen; + + error = ENOKEY; + + id = request_key(type, desc, NULL, destringid); + if (id >= 0 || errno == ENOMEM) + return id; + if (errno != ENOKEY) + error = errno; + + dlen = strlen(desc); + + f = fopen("/proc/keys", "r"); + if (!f) { + fprintf(stderr, "libkeyutils: Can't open /proc/keys: %m\n"); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) { + cp = strchr(buf, '\n'); + if (*cp) + *cp = '\0'; + + n = sscanf(buf, "%x %*s %*u %*s %*x %*d %*d %s %n", + &id, typebuf, &ndesc); + if (n == 2) { + if (strcmp(typebuf, type) != 0) + continue; + kdesc = buf + ndesc; + if (memcmp(kdesc, desc, dlen) != 0) + continue; + if (kdesc[dlen] != ':' && + kdesc[dlen] != '\0' && + kdesc[dlen] != ' ') + continue; + kdesc[dlen] = '\0'; + + /* The key type appends extra stuff to the end of the + * description after a colon in /proc/keys. Colons, + * however, are allowed in descriptions, so we need to + * make a further check. */ + n = keyctl_describe(id, rdesc, sizeof(rdesc) - 1); + if (n == -1) { + if (errno != ENOKEY) + error = errno; + if (errno == ENOMEM) + break; + } + if (n >= sizeof(rdesc) - 1) + continue; + rdesc[n] = '\0'; + + cp = strrchr(rdesc, ';'); + if (!cp) + continue; + cp++; + if (strcmp(cp, desc) != 0) + continue; + + fclose(f); + + if (destringid && + keyctl_link(id, destringid) == -1) + return -1; + + return id; + } + } + + fclose(f); + errno = error; + return -1; +} + #ifdef NO_GLIBC_KEYERR /*****************************************************************************/ /* @@ -162,5 +162,7 @@ typedef int (*recursive_key_scanner_t)(key_serial_t parent, key_serial_t key, char *desc, int desc_len, void *data); extern int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data); extern int recursive_session_key_scan(recursive_key_scanner_t func, void *data); +extern key_serial_t find_key_by_type_and_desc(const char *type, const char *desc, + key_serial_t destringid); #endif /* KEYUTILS_H */ diff --git a/version.lds b/version.lds index 3e6f475..034bc17 100644 --- a/version.lds +++ b/version.lds @@ -50,5 +50,6 @@ KEYUTILS_1.4 { /* utility functions */ recursive_key_scan; recursive_session_key_scan; + find_key_by_type_and_desc; } KEYUTILS_1.3; |