aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-09-10 18:38:02 +0100
committerDavid Howells <dhowells@redhat.com>2013-10-02 15:58:10 +0100
commit949159b53e688f6daa0e10dd50058a2dd929234d (patch)
tree4775421c4979f9a55af097a1460e08d62f92f417
parentb59512468561ffc3f85d1e808b5d2ae6a6313276 (diff)
downloadkeyutils-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.361
-rw-r--r--keyctl.34
-rw-r--r--keyutils.c83
-rw-r--r--keyutils.h2
-rw-r--r--version.lds1
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)
diff --git a/keyctl.3 b/keyctl.3
index 35bac2f..6801e77 100644
--- a/keyctl.3
+++ b/keyctl.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)
diff --git a/keyutils.c b/keyutils.c
index 329bfae..ca80900 100644
--- a/keyutils.c
+++ b/keyutils.c
@@ -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
/*****************************************************************************/
/*
diff --git a/keyutils.h b/keyutils.h
index 3ddaeae..74edfae 100644
--- a/keyutils.h
+++ b/keyutils.h
@@ -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;