aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2010-02-22 15:44:36 +0000
committerDavid Howells <dhowells@redhat.com>2010-02-22 16:02:29 +0000
commit53ad7681eedbe86ca729763ac2d75a90a451648a (patch)
treec8d4072f348de967f4ead0fc70719a7def1a5272
parent34718dc1040e93c2e2b2838f96f1f6a87564b598 (diff)
downloadkeyutils-53ad7681eedbe86ca729763ac2d75a90a451648a.tar.gz
keyutils historical version 0.3-3
- Added stdint.h inclusion in keyutils.h - Made request-key.c use request_key() rather than keyctl_search() - Added piping facility to request-key
-rw-r--r--keyutil.h1
-rw-r--r--keyutils.spec7
-rw-r--r--request-key.c205
-rw-r--r--request-key.conf1
-rw-r--r--request-key.conf.536
5 files changed, 201 insertions, 49 deletions
diff --git a/keyutil.h b/keyutil.h
index 6ca4a2d..5b78b31 100644
--- a/keyutil.h
+++ b/keyutil.h
@@ -12,6 +12,7 @@
#ifndef KEYUTIL_H
#define KEYUTIL_H
+#include <stdint.h>
/* key serial number */
typedef int32_t key_serial_t;
diff --git a/keyutils.spec b/keyutils.spec
index a10c147..1557ef6 100644
--- a/keyutils.spec
+++ b/keyutils.spec
@@ -5,7 +5,7 @@
Summary: Linux Key Management Utilities
Name: keyutils
Version: %{version}
-Release: 2
+Release: 3
License: GPL/LGPL
Group: System Environment/Base
ExclusiveOS: Linux
@@ -56,6 +56,11 @@ rm -rf $RPM_BUILD_ROOT
%{_includedir}/*
%changelog
+* Fri Nov 18 2005 David Howells <dhowells@redhat.com> - 0.3-3
+- Added stdint.h inclusion in keyutils.h
+- Made request-key.c use request_key() rather than keyctl_search()
+- Added piping facility to request-key
+
* Thu Nov 17 2005 David Howells <dhowells@redhat.com> - 0.3-2
- Added timeout keyctl option
- request_key auth keys must now be assumed
diff --git a/request-key.c b/request-key.c
index a6c2825..9b8863b 100644
--- a/request-key.c
+++ b/request-key.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <signal.h>
#include <syslog.h>
#include <unistd.h>
#include <fcntl.h>
@@ -114,6 +115,11 @@ static void error(const char *fmt, ...)
exit(1);
}
+static void oops(int x)
+{
+ error("Died on signal %d", x);
+}
+
/*****************************************************************************/
/*
*
@@ -122,7 +128,11 @@ int main(int argc, char *argv[])
{
key_serial_t key;
char *ktype, *kdesc, *buf, *callout_info;
- int ret, ntype, dpos, dlen;
+ int ret, ntype, dpos, dlen, fd;
+
+ signal(SIGSEGV, oops);
+ signal(SIGBUS, oops);
+ signal(SIGPIPE, SIG_IGN);
for (;;) {
if (argc > 1 && strcmp(argv[1], "-d") == 0) {
@@ -142,6 +152,21 @@ int main(int argc, char *argv[])
if (argc != 8 && argc != 9)
error("Unexpected argument count: %d\n", argc);
+ fd = open("/dev/null", O_RDWR);
+ if (fd < 0)
+ error("open");
+ if (fd > 2) {
+ close(fd);
+ }
+ else if (fd < 2) {
+ ret = dup(fd);
+ if (ret < 0)
+ error("dup failed: %m\n");
+
+ if (ret < 2 && dup(fd) < 0)
+ error("dup failed: %m\n");
+ }
+
xkey = argv[2];
xuid = argv[3];
xgid = argv[4];
@@ -157,7 +182,7 @@ int main(int argc, char *argv[])
error("Failed to assume authority over key %d (%m)\n", key);
/* ask the kernel to describe the key to us */
- if (xdebug <= 0) {
+ if (xdebug < 2) {
ret = keyctl_describe_alloc(key, &buf);
if (ret < 0)
goto inaccessible;
@@ -195,6 +220,8 @@ int main(int argc, char *argv[])
callout_info = tmp;
}
+ debug("CALLOUT: '%s'\n", callout_info);
+
/* determine the action to perform */
lookup_action(argv[1], /* op */
key, /* ID of key under construction */
@@ -318,6 +345,8 @@ static void lookup_action(char *op,
if (!*p)
goto syntax_error;
+ fclose(conf);
+
execute_program(op, key, ktype, kdesc, callout_info, p);
}
@@ -405,7 +434,7 @@ static void execute_program(char *op,
char *prog, *p, *q;
int argc, pipeit;
- debug("execute_program('%s')\n", cmdline);
+ debug("execute_program('%s','%s')\n", callout_info, cmdline);
/* if the commandline begins with a bar, then we pipe the callout data into it and read
* back the payload data
@@ -420,9 +449,11 @@ static void execute_program(char *op,
/* extract the path to the program to run */
prog = p = cmdline;
while (*p && !isspace(*p)) p++;
- if (!*p)
- error("/etc/request-key.conf:%d: No command path\n", confline);
- *p++ = 0;
+// if (!*p)
+// error("/etc/request-key.conf:%d: No command path\n", confline);
+// *p++ = 0;
+ if (*p)
+ *p++ = 0;
argv[0] = strrchr(prog, '/') + 1;
@@ -479,7 +510,7 @@ static void execute_program(char *op,
/* keysub macro */
if (*q == '{') {
- key_serial_t rqsession, keysub;
+ key_serial_t keysub;
void *tmp;
char *ksdesc, *end, *subdata;
int ret, loop;
@@ -511,10 +542,10 @@ static void execute_program(char *op,
error("/etc/request-key.conf:%d: Keysub description empty\n",
confline);
- /* look up the key in the requestor's session keyring */
- rqsession = atoi(xsession_keyring);
-
- keysub = keyctl_search(rqsession, q, ksdesc, 0);
+ /* look up the key in the requestor's keyrings, but fail immediately if the
+ * key is not found rather than invoking /sbin/request-key again
+ */
+ keysub = request_key(q, ksdesc, NULL, 0);
if (keysub < 0)
error("/etc/request-key.conf:%d:"
" Keysub key not found: %m\n",
@@ -546,7 +577,7 @@ static void execute_program(char *op,
if (xdebug) {
char **ap;
- debug("%s %s\n", pipeit ? "Run" : "PipeThru", prog);
+ debug("%s %s\n", pipeit ? "PipeThru" : "Run", prog);
for (ap = argv; *ap; ap++)
debug("- argv[%zd] = \"%s\"\n", ap - argv, *ap);
}
@@ -581,10 +612,13 @@ static void pipe_to_program(char *op,
char *prog,
char **argv)
{
- char payload[32768 + 1], *pp, *pc;
- int ipi[2], opi[2], childpid, ifl, ofl, npay, ninfo, tmp;
+ char errbuf[512], payload[32768 + 1], *pp, *pc, *pe;
+ int ipi[2], opi[2], epi[2], childpid;
+ int ifl, ofl, efl, npay, ninfo, espace, tmp;
- if (pipe(ipi) < 0 || pipe(opi) < 0)
+ debug("pipe_to_program(%s -> %s)", callout_info, prog);
+
+ if (pipe(ipi) < 0 || pipe(opi) < 0 || pipe(epi) < 0)
error("pipe failed: %m");
childpid = fork();
@@ -594,12 +628,15 @@ static void pipe_to_program(char *op,
if (childpid == 0) {
/* child process */
if (dup2(ipi[0], 0) < 0 ||
- dup2(opi[1], 1) < 0)
+ dup2(opi[1], 1) < 0 ||
+ dup2(epi[1], 2) < 0)
error("dup2 failed: %m");
close(ipi[0]);
close(ipi[1]);
close(opi[0]);
close(opi[1]);
+ close(epi[0]);
+ close(epi[1]);
execv(prog, argv);
error("/etc/request-key.conf:%d: Failed to execute '%s': %m\n", confline, prog);
@@ -608,27 +645,35 @@ static void pipe_to_program(char *op,
/* parent process */
close(ipi[0]);
close(opi[1]);
+ close(epi[1]);
#define TOSTDIN ipi[1]
#define FROMSTDOUT opi[0]
+#define FROMSTDERR epi[0]
ifl = fcntl(TOSTDIN, F_GETFL);
ofl = fcntl(FROMSTDOUT, F_GETFL);
- if (ifl < 0 || ofl < 0)
+ efl = fcntl(FROMSTDERR, F_GETFL);
+ if (ifl < 0 || ofl < 0 || efl < 0)
error("fcntl/F_GETFL failed: %m");
ifl |= O_NONBLOCK;
ofl |= O_NONBLOCK;
+ efl |= O_NONBLOCK;
if (fcntl(TOSTDIN, F_SETFL, ifl) < 0 ||
- fcntl(FROMSTDOUT, F_SETFL, ofl) < 0)
+ fcntl(FROMSTDOUT, F_SETFL, ofl) < 0 ||
+ fcntl(FROMSTDERR, F_SETFL, efl) < 0)
error("fcntl/F_SETFL failed: %m");
+ ninfo = strlen(callout_info);
+ pc = callout_info;
+
npay = sizeof(payload);
pp = payload;
- ninfo = strlen(callout_info);
- pc = callout_info;
+ espace = sizeof(errbuf);
+ pe = errbuf;
do {
fd_set rfds, wfds;
@@ -637,57 +682,134 @@ static void pipe_to_program(char *op,
FD_ZERO(&wfds);
if (TOSTDIN != -1) {
- if (npay > 0) {
+ if (ninfo > 0) {
FD_SET(TOSTDIN, &wfds);
}
else {
close(TOSTDIN);
TOSTDIN = -1;
-
- if (FROMSTDOUT == -1)
- break;
+ continue;
}
}
- if (FROMSTDOUT)
+ if (FROMSTDOUT != -1)
FD_SET(FROMSTDOUT, &rfds);
+ if (FROMSTDERR != -1)
+ FD_SET(FROMSTDERR, &rfds);
+
tmp = TOSTDIN > FROMSTDOUT ? TOSTDIN : FROMSTDOUT;
+ tmp = tmp > FROMSTDERR ? tmp : FROMSTDERR;
tmp++;
+ debug("select r=%d,%d w=%d m=%d\n", FROMSTDOUT, FROMSTDERR, TOSTDIN, tmp);
+
tmp = select(tmp, &rfds, &wfds, NULL, NULL);
if (tmp < 0)
- error("select failed: %m");
+ error("select failed: %m\n");
- if (FD_ISSET(TOSTDIN, &wfds)) {
+ debug("select -> %d r=%x w=%x\n", tmp, *(unsigned *) &rfds, *(unsigned *) &wfds);
+
+ if (TOSTDIN != -1 && FD_ISSET(TOSTDIN, &wfds)) {
tmp = write(TOSTDIN, pc, ninfo);
- if (tmp < 0)
- error("write failed: %m");
- pc += tmp;
- ninfo -= tmp;
+ if (tmp < 0) {
+ if (errno != EPIPE)
+ error("write failed: %m\n");
+
+ debug("EPIPE");
+ ninfo = 0;
+ }
+ else {
+ debug("wrote %d\n", tmp);
+
+ pc += tmp;
+ ninfo -= tmp;
+ }
}
- if (FD_ISSET(FROMSTDOUT, &rfds)) {
+ if (FROMSTDOUT != -1 && FD_ISSET(FROMSTDOUT, &rfds)) {
tmp = read(FROMSTDOUT, pp, npay);
if (tmp < 0)
- error("read failed: %m");
+ error("read failed: %m\n");
+
+ debug("read %d\n", tmp);
if (tmp == 0) {
close(FROMSTDOUT);
- close(TOSTDIN);
FROMSTDOUT = -1;
- TOSTDIN = -1;
}
else {
pp += tmp;
npay -= tmp;
if (npay == 0)
- error("Too much data read from query program");
+ error("Too much data read from query program\n");
}
}
- } while (TOSTDIN != -1 && FROMSTDOUT != -1);
+ if (FROMSTDERR != -1 && FD_ISSET(FROMSTDERR, &rfds)) {
+ char *nl;
+
+ tmp = read(FROMSTDERR, pe, espace);
+ if (tmp < 0)
+ error("read failed: %m\n");
+
+ debug("read err %d\n", tmp);
+
+ if (tmp == 0) {
+ close(FROMSTDERR);
+ FROMSTDERR = -1;
+ continue;
+ }
+
+ pe += tmp;
+ espace -= tmp;
+
+ while ((nl = memchr(errbuf, '\n', pe - errbuf))) {
+ int n, rest;
+
+ nl++;
+ n = nl - errbuf;
+
+ if (xdebug)
+ fprintf(stderr, "Child: %*.*s", n, n, errbuf);
+
+ if (!xnolog) {
+ openlog("request-key", 0, LOG_AUTHPRIV);
+ syslog(LOG_ERR, "Child: %*.*s", n, n, errbuf);
+ closelog();
+ }
+
+ rest = pe - nl;
+ if (rest > 0) {
+ memmove(errbuf, nl, rest);
+ pe -= n;
+ espace += n;
+ }
+ else {
+ pe = errbuf;
+ espace = sizeof(errbuf);
+ }
+ }
+
+ if (espace == 0) {
+ int n = sizeof(errbuf);
+
+ if (xdebug)
+ fprintf(stderr, "Child: %*.*s", n, n, errbuf);
+
+ if (!xnolog) {
+ openlog("request-key", 0, LOG_AUTHPRIV);
+ syslog(LOG_ERR, "Child: %*.*s", n, n, errbuf);
+ closelog();
+ }
+
+ pe = errbuf;
+ espace = sizeof(errbuf);
+ }
+ }
+
+ } while (TOSTDIN != -1 || FROMSTDOUT != -1 || FROMSTDERR != -1);
/* wait for the program to exit */
if (waitpid(childpid, &tmp, 0) != childpid)
@@ -704,7 +826,7 @@ static void pipe_to_program(char *op,
norecurse = 1;
debug("child exited %d\n", WEXITSTATUS(tmp));
- lookup_action(op, key, ktype, kdesc, "negate");
+ lookup_action("negate", key, ktype, kdesc, callout_info);
}
if (WIFSIGNALED(tmp)) {
@@ -713,13 +835,16 @@ static void pipe_to_program(char *op,
norecurse = 1;
debug("child died on signal %d\n", WTERMSIG(tmp));
- lookup_action(op, key, ktype, kdesc, "negate");
+ lookup_action("negate", key, ktype, kdesc, callout_info);
}
/* attempt to instantiate the key */
- if (tmp < keyctl_instantiate(key, payload, pp - payload, 0))
+ debug("instantiate with %zd bytes\n", pp - payload);
+
+ if (keyctl_instantiate(key, payload, pp - payload, 0) < 0)
error("instantiate key failed: %m\n");
+ debug("instantiation successful\n");
exit(0);
} /* end pipe_to_program() */
diff --git a/request-key.conf b/request-key.conf
index e78fa0a..e482c96 100644
--- a/request-key.conf
+++ b/request-key.conf
@@ -32,5 +32,6 @@
#OP TYPE DESCRIPTION CALLOUT INFO PROGRAM ARG1 ARG2 ARG3 ...
#====== ======= =============== =============== ===============================
create user debug:* negate /bin/keyctl negate %k 30 %S
+create user debug:loop:* * |/bin/cat
create user debug:* * /usr/share/keyutils/request-key-debug.sh %k %d %c %S
negate * * * /bin/keyctl negate %k 30 %S
diff --git a/request-key.conf.5 b/request-key.conf.5
index 97abbbe..eb22c9e 100644
--- a/request-key.conf.5
+++ b/request-key.conf.5
@@ -1,5 +1,5 @@
-.\"
-.\" Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+.\" -*- nroff -*-
+.\" 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
@@ -40,6 +40,14 @@ Should a match be made, the program specified by <prog> will be exec'd. This
must have a fully qualified path name. argv[0] will be set from the part of the
program name that follows the last slash '/' character.
.P
+If the program name is prefixed with a pipe bar character '|', then the program
+will be forked and exec'd attached to three pipes. The callout information will
+be piped to it on it's stdin and the intended payload data will be retrieved
+from its stdout. Anything sent to stderr will be posted in syslog. If the
+program exits 0, then /sbin/request-key will attempt to instantiate the key
+with the data read from stdout. If it fails in any other way, then request-key
+will attempt to execute the appropriate 'negate' operation command.
+.P
The program arguments can be substituted with various macros. Only complete
argument substitution is supported - macro substitutions can't be embedded. All
macros begin with a percent character '%'. An argument beginning with two
@@ -77,18 +85,22 @@ contents of a key:
.RE
.P
This performs a lookup for a key of the given type and description on the
-requestor's session keyring, and if found, substitutes the contents for the
-macro. If not found an error will be logged and the key under construction will
-be negated.
+requestor's keyrings, and if found, substitutes the contents for the macro. If
+not found an error will be logged and the key under construction will be
+negated.
.SH EXAMPLE
.P
A basic file will be installed in the /etc. This will contain two debugging
lines that can be used to test the installation:
.P
.RS
-create user debug:* negate /bin/keyctl %k negate 30 %S
+create user debug:* negate /bin/keyctl negate %k 30 %S
+.br
+create user debug:loop:* * |/bin/cat
.br
create user debug:* * /usr/share/keyutils/request-key-debug.sh %k %d %c %S
+.br
+negate * * * /bin/keyctl negate %k 30 %S
.RE
.P
This is set up so that something like:
@@ -97,13 +109,21 @@ This is set up so that something like:
keyctl request2 user debug:xxxx negate
.RE
.P
-will create a negative user-defined key, and something like:
+will create a negative user-defined key, something like:
.P
.RS
keyctl request2 user debug:yyyy spoon
.RE
.P
-will create an instantiated user-defined key with "Debug spoon" as the payload.
+will create an instantiated user-defined key with "Debug spoon" as the payload,
+and something like:
+.P
+.RS
+keyctl request2 user debug:loop:zzzz abcdefghijkl
+.RE
+.P
+will create an instantiated user-defined key with the callout information as
+the payload.
.SH FILES
.ul
/etc/request-key.conf