diff options
author | David Howells <dhowells@redhat.com> | 2010-02-22 15:44:36 +0000 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2010-02-22 16:02:29 +0000 |
commit | 53ad7681eedbe86ca729763ac2d75a90a451648a (patch) | |
tree | c8d4072f348de967f4ead0fc70719a7def1a5272 | |
parent | 34718dc1040e93c2e2b2838f96f1f6a87564b598 (diff) | |
download | keyutils-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.h | 1 | ||||
-rw-r--r-- | keyutils.spec | 7 | ||||
-rw-r--r-- | request-key.c | 205 | ||||
-rw-r--r-- | request-key.conf | 1 | ||||
-rw-r--r-- | request-key.conf.5 | 36 |
5 files changed, 201 insertions, 49 deletions
@@ -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 |