diff options
Diffstat (limited to 'modules/pam_namespace')
-rw-r--r-- | modules/pam_namespace/.cvsignore | 9 | ||||
-rw-r--r-- | modules/pam_namespace/Makefile.am | 42 | ||||
-rw-r--r-- | modules/pam_namespace/README.xml | 44 | ||||
-rw-r--r-- | modules/pam_namespace/argv_parse.c | 165 | ||||
-rw-r--r-- | modules/pam_namespace/argv_parse.h | 43 | ||||
-rw-r--r-- | modules/pam_namespace/md5.c | 260 | ||||
-rw-r--r-- | modules/pam_namespace/md5.h | 28 | ||||
-rw-r--r-- | modules/pam_namespace/namespace.conf | 28 | ||||
-rw-r--r-- | modules/pam_namespace/namespace.conf.5.xml | 210 | ||||
-rwxr-xr-x | modules/pam_namespace/namespace.init | 24 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.8.xml | 390 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.c | 1907 | ||||
-rw-r--r-- | modules/pam_namespace/pam_namespace.h | 168 | ||||
-rwxr-xr-x | modules/pam_namespace/tst-pam_namespace | 2 |
14 files changed, 0 insertions, 3320 deletions
diff --git a/modules/pam_namespace/.cvsignore b/modules/pam_namespace/.cvsignore deleted file mode 100644 index 59a9578c..00000000 --- a/modules/pam_namespace/.cvsignore +++ /dev/null @@ -1,9 +0,0 @@ -*.la -*.lo -.deps -.libs -Makefile -Makefile.in -README -namespace.conf.5 -pam_namespace.8 diff --git a/modules/pam_namespace/Makefile.am b/modules/pam_namespace/Makefile.am deleted file mode 100644 index 05d47cf3..00000000 --- a/modules/pam_namespace/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright (c) 2006 Red Hat, Inc. -# - -CLEANFILES = *~ -MAN5 = namespace.conf.5 -MAN8 = pam_namespace.8 - -XMLS = README.xml namespace.conf.5.xml pam_namespace.8.xml - -if ENABLE_REGENERATE_MAN -noinst_DATA = README --include $(top_srcdir)/Make.xml.rules -endif - -EXTRA_DIST = README namespace.conf namespace.init $(MAN5) $(MAN8) $(XMLS) tst-pam_namespace - -noinst_HEADERS = md5.h pam_namespace.h argv_parse.h - -securelibdir = $(SECUREDIR) -secureconfdir = $(SCONFIGDIR) -namespaceddir = $(SCONFIGDIR)/namespace.d - -AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ - -DSECURECONF_DIR=\"$(SCONFIGDIR)/\" -AM_LDFLAGS = -no-undefined -avoid-version -module -if HAVE_VERSIONING - AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map -endif - -if HAVE_UNSHARE -securelib_LTLIBRARIES = pam_namespace.la -pam_namespace_la_SOURCES = pam_namespace.c md5.c argv_parse.c -pam_namespace_la_LIBADD = -L$(top_builddir)/libpam -lpam @LIBSELINUX@ - -secureconf_DATA = namespace.conf -secureconf_SCRIPTS = namespace.init -namespaced_DATA = - -TESTS = tst-pam_namespace -man_MANS = $(MAN5) $(MAN8) -endif diff --git a/modules/pam_namespace/README.xml b/modules/pam_namespace/README.xml deleted file mode 100644 index 4ef99c9f..00000000 --- a/modules/pam_namespace/README.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" -"http://www.docbook.org/xml/4.3/docbookx.dtd" -[ -<!-- -<!ENTITY pamns SYSTEM "pam_namespace.8.xml"> ---> -<!-- -<!ENTITY nsconf SYSTEM "namespace.conf.5.xml"> ---> -]> - -<article> - - <articleinfo> - - <title> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_namespace.8.xml" xpointer='xpointer(//refnamediv[@id = "pam_namespace-name"]/*)'/> - </title> - - </articleinfo> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_namespace.8.xml" xpointer='xpointer(//refsect1[@id = "pam_namespace-description"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="pam_namespace.8.xml" xpointer='xpointer(//refsect1[@id = "pam_namespace-options"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="namespace.conf.5.xml" xpointer='xpointer(//refsect1[@id = "namespace.conf-description"]/*)'/> - </section> - - <section> - <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" - href="namespace.conf.5.xml" xpointer='xpointer(//refsect1[@id = "namespace.conf-examples"]/*)'/> - </section> - -</article> diff --git a/modules/pam_namespace/argv_parse.c b/modules/pam_namespace/argv_parse.c deleted file mode 100644 index acc76d74..00000000 --- a/modules/pam_namespace/argv_parse.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * argv_parse.c --- utility function for parsing a string into a - * argc, argv array. - * - * This file defines a function argv_parse() which parsing a - * passed-in string, handling double quotes and backslashes, and - * creates an allocated argv vector which can be freed using the - * argv_free() function. - * - * See argv_parse.h for the formal definition of the functions. - * - * Copyright 1999 by Theodore Ts'o. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose with or without fee is hereby granted, provided that - * the above copyright notice and this permission notice appear in all - * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE - * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't - * it sick that the U.S. culture of lawsuit-happy lawyers requires - * this kind of disclaimer?) - * - * Version 1.1, modified 2/27/1999 - */ - -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include "argv_parse.h" - -#define STATE_WHITESPACE 1 -#define STATE_TOKEN 2 -#define STATE_QUOTED 3 - -/* - * Returns 0 on success, -1 on failure. - */ -int argv_parse(const char *in_buf, int *ret_argc, char ***ret_argv) -{ - int argc = 0, max_argc = 0; - char **argv, **new_argv, *buf, ch; - const char *cp = 0; - char *outcp = 0; - int state = STATE_WHITESPACE; - - buf = malloc(strlen(in_buf)+1); - if (!buf) - return -1; - - max_argc = 0; argc = 0; argv = 0; - outcp = buf; - for (cp = in_buf; (ch = *cp); cp++) { - if (state == STATE_WHITESPACE) { - if (isspace((int) ch)) - continue; - /* Not whitespace, so start a new token */ - state = STATE_TOKEN; - if (argc >= max_argc) { - max_argc += 3; - new_argv = realloc(argv, - (max_argc+1)*sizeof(char *)); - if (!new_argv) { - if (argv) free(argv); - free(buf); - return -1; - } - argv = new_argv; - } - argv[argc++] = outcp; - } - if (state == STATE_QUOTED) { - if (ch == '"') - state = STATE_TOKEN; - else - *outcp++ = ch; - continue; - } - /* Must be processing characters in a word */ - if (isspace((int) ch)) { - /* - * Terminate the current word and start - * looking for the beginning of the next word. - */ - *outcp++ = 0; - state = STATE_WHITESPACE; - continue; - } - if (ch == '"') { - state = STATE_QUOTED; - continue; - } - if (ch == '\\') { - ch = *++cp; - switch (ch) { - case '\0': - ch = '\\'; cp--; break; - case 'n': - ch = '\n'; break; - case 't': - ch = '\t'; break; - case 'b': - ch = '\b'; break; - } - } - *outcp++ = ch; - } - if (state != STATE_WHITESPACE) - *outcp++ = '\0'; - if (argv == 0) { - argv = malloc(sizeof(char *)); - free(buf); - } - argv[argc] = 0; - if (ret_argc) - *ret_argc = argc; - if (ret_argv) - *ret_argv = argv; - return 0; -} - -void argv_free(char **argv) -{ - if (*argv) - free(*argv); - free(argv); -} - -#ifdef DEBUG_ARGV_PARSE -/* - * For debugging - */ - -#include <stdio.h> - -int main(int argc, char **argv) -{ - int ac, ret; - char **av, **cpp; - char buf[256]; - - while (!feof(stdin)) { - if (fgets(buf, sizeof(buf), stdin) == NULL) - break; - ret = argv_parse(buf, &ac, &av); - if (ret != 0) { - printf("Argv_parse returned %d!\n", ret); - continue; - } - printf("Argv_parse returned %d arguments...\n", ac); - for (cpp = av; *cpp; cpp++) { - if (cpp != av) - printf(", "); - printf("'%s'", *cpp); - } - printf("\n"); - argv_free(av); - } - exit(0); -} -#endif diff --git a/modules/pam_namespace/argv_parse.h b/modules/pam_namespace/argv_parse.h deleted file mode 100644 index c7878fc1..00000000 --- a/modules/pam_namespace/argv_parse.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * argv_parse.h --- header file for the argv parser. - * - * This file defines the interface for the functions argv_parse() and - * argv_free(). - * - *********************************************************************** - * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv) - * - * This function takes as its first argument a string which it will - * parse into an argv argument vector, with each white-space separated - * word placed into its own slot in the argv. This function handles - * double quotes and backslashes so that the parsed words can contain - * special characters. The count of the number words found in the - * parsed string, as well as the argument vector, are returned into - * ret_argc and ret_argv, respectively. - *********************************************************************** - * extern void argv_free(char **argv); - * - * This function frees the argument vector created by argv_parse(). - *********************************************************************** - * - * Copyright 1999 by Theodore Ts'o. - * - * Permission to use, copy, modify, and distribute this software for - * any purpose with or without fee is hereby granted, provided that - * the above copyright notice and this permission notice appear in all - * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE - * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't - * it sick that the U.S. culture of lawsuit-happy lawyers requires - * this kind of disclaimer?) - * - * Version 1.1, modified 2/27/1999 - */ - -extern int argv_parse(const char *in_buf, int *ret_argc, char ***ret_argv); -extern void argv_free(char **argv); diff --git a/modules/pam_namespace/md5.c b/modules/pam_namespace/md5.c deleted file mode 100644 index 3094a130..00000000 --- a/modules/pam_namespace/md5.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * $Id$ - * - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - */ - -#include <string.h> -#include "md5.h" - -#define MD5Name(x) x - -#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) -#define byteReverse(buf, len) /* Nothing */ -#else -static void byteReverse(unsigned char *buf, unsigned longs); - -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - uint32 t; - do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Name(MD5Init)(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301U; - ctx->buf[1] = 0xefcdab89U; - ctx->buf[2] = 0x98badcfeU; - ctx->buf[3] = 0x10325476U; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Name(MD5Update)(struct MD5Context *ctx, unsigned const char *buf, unsigned len) -{ - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Name(MD5Final)(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Name(MD5Transform)(ctx->buf, (uint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void MD5Name(MD5Transform)(uint32 buf[4], uint32 const in[16]) -{ - register uint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478U, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756U, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070dbU, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceeeU, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0fafU, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62aU, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613U, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501U, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8U, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7afU, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1U, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7beU, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122U, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193U, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438eU, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821U, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562U, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340U, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51U, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aaU, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105dU, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453U, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681U, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8U, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6U, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6U, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87U, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14edU, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905U, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8U, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9U, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8aU, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942U, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681U, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122U, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380cU, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44U, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9U, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60U, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70U, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6U, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127faU, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085U, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05U, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039U, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5U, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8U, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665U, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244U, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97U, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7U, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039U, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3U, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92U, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47dU, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1U, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4fU, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0U, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314U, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1U, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82U, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235U, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bbU, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391U, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -void MD5Name(MD5)(unsigned const char *buf, unsigned len, unsigned char digest[16]) -{ - struct MD5Context ctx; - MD5Name(MD5Init)(&ctx); - MD5Name(MD5Update)(&ctx, buf, len); - MD5Name(MD5Final)(digest, &ctx); -} diff --git a/modules/pam_namespace/md5.h b/modules/pam_namespace/md5.h deleted file mode 100644 index 73f85833..00000000 --- a/modules/pam_namespace/md5.h +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef MD5_H -#define MD5_H - -typedef unsigned int uint32; - -struct MD5Context { - uint32 buf[4]; - uint32 bits[2]; - unsigned char in[64]; -}; - -#define MD5_DIGEST_LENGTH 16 - -void MD5Init(struct MD5Context *); -void MD5Update(struct MD5Context *, unsigned const char *, unsigned); -void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], struct MD5Context *); -void MD5Transform(uint32 buf[4], uint32 const in[MD5_DIGEST_LENGTH]); -void MD5(unsigned const char *, unsigned, unsigned char digest[MD5_DIGEST_LENGTH]); - - -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ - -typedef struct MD5Context MD5_CTX; - -#endif /* MD5_H */ diff --git a/modules/pam_namespace/namespace.conf b/modules/pam_namespace/namespace.conf deleted file mode 100644 index f973225f..00000000 --- a/modules/pam_namespace/namespace.conf +++ /dev/null @@ -1,28 +0,0 @@ -# /etc/security/namespace.conf -# -# See /usr/share/doc/pam-*/txts/README.pam_namespace for more information. -# -# Uncommenting the following three lines will polyinstantiate -# /tmp, /var/tmp and user's home directories. /tmp and /var/tmp will -# be polyinstantiated based on the MLS level part of the security context as well as user -# name, Polyinstantion will not be performed for user root and adm for directories -# /tmp and /var/tmp, whereas home directories will be polyinstantiated for all users. -# The user name and context is appended to the instance prefix. -# -# Note that instance directories do not have to reside inside the -# polyinstantiated directory. In the examples below, instances of /tmp -# will be created in /tmp-inst directory, where as instances of /var/tmp -# and users home directories will reside within the directories that -# are being polyinstantiated. -# -# Instance parent directories must exist for the polyinstantiation -# mechanism to work. By default, they should be created with the mode -# of 000. pam_namespace module will enforce this mode unless it -# is explicitly called with an argument to ignore the mode of the -# instance parent. System administrators should use this argument with -# caution, as it will reduce security and isolation achieved by -# polyinstantiation. -# -#/tmp /tmp-inst/ level root,adm -#/var/tmp /var/tmp/tmp-inst/ level root,adm -#$HOME $HOME/$USER.inst/ level diff --git a/modules/pam_namespace/namespace.conf.5.xml b/modules/pam_namespace/namespace.conf.5.xml deleted file mode 100644 index a1769600..00000000 --- a/modules/pam_namespace/namespace.conf.5.xml +++ /dev/null @@ -1,210 +0,0 @@ -<?xml version="1.0" encoding='UTF-8'?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" - "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"> - -<refentry id="namespace.conf"> - - <refmeta> - <refentrytitle>namespace.conf</refentrytitle> - <manvolnum>5</manvolnum> - <refmiscinfo class="sectdesc">Linux-PAM Manual</refmiscinfo> - </refmeta> - - <refnamediv> - <refname>namespace.conf</refname> - <refpurpose>the namespace configuration file</refpurpose> - </refnamediv> - - - <refsect1 id='namespace.conf-description'> - <title>DESCRIPTION</title> - - <para> - The <emphasis>pam_namespace.so</emphasis> module allows setup of - private namespaces with polyinstantiated directories. - Directories can be polyinstantiated based on user name - or, in the case of SELinux, user name, sensitivity level or complete security context. If an - executable script <filename>/etc/security/namespace.init</filename> - exists, it is used to initialize the namespace every time a new instance - directory is setup. The script receives the polyinstantiated - directory path and the instance directory path as its arguments. - </para> - - <para> - The <filename>/etc/security/namespace.conf</filename> file specifies - which directories are polyinstantiated, how they are polyinstantiated, - how instance directories would be named, and any users for whom - polyinstantiation would not be performed. - </para> - - <para> - When someone logs in, the file <filename>namespace.conf</filename> is - scanned. Comments are marked by <emphasis>#</emphasis> characters. - Each non comment line represents one polyinstantiated - directory. The fields are separated by spaces but can be quoted by - <emphasis>"</emphasis> characters also escape - sequences <emphasis>\b</emphasis>, <emphasis>\n</emphasis>, and - <emphasis>\t</emphasis> are recognized. The fields are as follows: - </para> - - <para><replaceable>polydir</replaceable> <replaceable>instance_prefix</replaceable> <replaceable>method</replaceable> <replaceable>list_of_uids</replaceable> - </para> - - <para> - The first field, <replaceable>polydir</replaceable>, is the absolute - pathname of the directory to polyinstantiate. The special string - <emphasis>$HOME</emphasis> is replaced with the user's home directory, - and <emphasis>$USER</emphasis> with the username. This field cannot - be blank. - </para> - - <para> - The second field, <replaceable>instance_prefix</replaceable> is - the string prefix used to build the pathname for the instantiation - of <polydir>. Depending on the polyinstantiation - <replaceable>method</replaceable> it is then appended with - "instance differentiation string" to generate the final - instance directory path. This directory is created if it did not exist - already, and is then bind mounted on the <polydir> to provide an - instance of <polydir> based on the <method> column. - The special string <emphasis>$HOME</emphasis> is replaced with the - user's home directory, and <emphasis>$USER</emphasis> with the username. - This field cannot be blank. - </para> - - <para> - The third field, <replaceable>method</replaceable>, is the method - used for polyinstantiation. It can take these values; "user" - for polyinstantiation based on user name, "level" for - polyinstantiation based on process MLS level and user name, "context" for - polyinstantiation based on process security context and user name, - "tmpfs" for mounting tmpfs filesystem as an instance dir, and - "tmpdir" for creating temporary directory as an instance dir which is - removed when the user's session is closed. - Methods "context" and "level" are only available with SELinux. This - field cannot be blank. - </para> - - <para> - The fourth field, <replaceable>list_of_uids</replaceable>, is - a comma separated list of user names for whom the polyinstantiation - is not performed. If left blank, polyinstantiation will be performed - for all users. If the list is preceded with a single "~" character, - polyinstantiation is performed only for users in the list. - </para> - - <para> - The <replaceable>method</replaceable> field can contain also following - optional flags separated by <emphasis>:</emphasis> characters. - </para> - - <para><emphasis>create</emphasis>=<replaceable>mode</replaceable>,<replaceable>owner</replaceable>,<replaceable>group</replaceable> - - create the polyinstantiated directory. The mode, owner and group parameters - are optional. The default for mode is determined by umask, the default - owner is the user whose session is opened, the default group is the - primary group of the user. - </para> - - <para><emphasis>iscript</emphasis>=<replaceable>path</replaceable> - - path to the instance directory init script. The base directory for relative - paths is <filename>/etc/security/namespace.d</filename>. - </para> - - <para><emphasis>noinit</emphasis> - - instance directory init script will not be executed. - </para> - - <para><emphasis>shared</emphasis> - - the instance directories for "context" and "level" methods will not - contain the user name and will be shared among all users. - </para> - - <para> - The directory where polyinstantiated instances are to be - created, must exist and must have, by default, the mode of 0000. The - requirement that the instance parent be of mode 0000 can be overridden - with the command line option <emphasis>ignore_instance_parent_mode</emphasis> - </para> - - <para> - In case of context or level polyinstantiation the SELinux context - which is used for polyinstantiation is the context used for executing - a new process as obtained by getexeccon. This context must be set - by the calling application or <filename>pam_selinux.so</filename> - module. If this context is not set the polyinstatiation will be - based just on user name. - </para> - - <para> - The "instance differentiation string" is <user name> for "user" - method and <user name>_<raw directory context> for "context" - and "level" methods. If the whole string is too long the end of it is - replaced with md5sum of itself. Also when command line option - <emphasis>gen_hash</emphasis> is used the whole string is replaced - with md5sum of itself. - </para> - - </refsect1> - - <refsect1 id="namespace.conf-examples"> - <title>EXAMPLES</title> - <para> - These are some example lines which might be specified in - <filename>/etc/security/namespace.conf</filename>. - </para> - - <literallayout> - # The following three lines will polyinstantiate /tmp, - # /var/tmp and user's home directories. /tmp and /var/tmp - # will be polyinstantiated based on the security level - # as well as user name, whereas home directory will be - # polyinstantiated based on the full security context and user name. - # Polyinstantiation will not be performed for user root - # and adm for directories /tmp and /var/tmp, whereas home - # directories will be polyinstantiated for all users. - # - # Note that instance directories do not have to reside inside - # the polyinstantiated directory. In the examples below, - # instances of /tmp will be created in /tmp-inst directory, - # where as instances of /var/tmp and users home directories - # will reside within the directories that are being - # polyinstantiated. - # - /tmp /tmp-inst/ level root,adm - /var/tmp /var/tmp/tmp-inst/ level root,adm - $HOME $HOME/$USER.inst/inst- context - </literallayout> - - <para> - For the <service>s you need polyinstantiation (login for example) - put the following line in /etc/pam.d/<service> as the last line for - session group: - </para> - - <para> - session required pam_namespace.so [arguments] - </para> - - <para> - This module also depends on pam_selinux.so setting the context. - </para> - - </refsect1> - - <refsect1 id="namespace.conf-see_also"> - <title>SEE ALSO</title> - <para> - <citerefentry><refentrytitle>pam_namespace</refentrytitle><manvolnum>8</manvolnum></citerefentry>, - <citerefentry><refentrytitle>pam.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>, - <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry> - </para> - </refsect1> - - <refsect1 id="namespace.conf-author"> - <title>AUTHORS</title> - <para> - The namespace.conf manual page was written by Janak Desai <janak@us.ibm.com>. - More features added by Tomas Mraz <tmraz@redhat.com>. - </para> - </refsect1> -</refentry> diff --git a/modules/pam_namespace/namespace.init b/modules/pam_namespace/namespace.init deleted file mode 100755 index 424c6d0c..00000000 --- a/modules/pam_namespace/namespace.init +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -p -# It receives polydir path as $1, the instance path as $2, -# a flag whether the instance dir was newly created (0 - no, 1 - yes) in $3, -# and user name in $4. -# -# The following section will copy the contents of /etc/skel if this is a -# newly created home directory. -if [ "$3" = 1 ]; then - # This line will fix the labeling on all newly created directories - [ -x /sbin/restorecon ] && /sbin/restorecon "$1" - user="$4" - passwd=$(getent passwd "$user") - homedir=$(echo "$passwd" | cut -f6 -d":") - if [ "$1" = "$homedir" ]; then - gid=$(echo "$passwd" | cut -f4 -d":") - cp -rT /etc/skel "$homedir" - chown -R "$user":"$gid" "$homedir" - mode=$(awk '/^UMASK/{gsub("#.*$", "", $2); printf "%o", and(0777,compl(strtonum("0" $2))); exit}' /etc/login.defs) - chmod ${mode:-700} "$homedir" - [ -x /sbin/restorecon ] && /sbin/restorecon -R "$homedir" - fi -fi - -exit 0 diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml deleted file mode 100644 index 32c5359d..00000000 --- a/modules/pam_namespace/pam_namespace.8.xml +++ /dev/null @@ -1,390 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"> - -<refentry id='pam_namespace'> - - <refmeta> - <refentrytitle>pam_namespace</refentrytitle> - <manvolnum>8</manvolnum> - <refmiscinfo class='setdesc'>Linux-PAM Manual</refmiscinfo> - </refmeta> - - <refnamediv id='pam_namespace-name'> - <refname>pam_namespace</refname> - <refpurpose> - PAM module for configuring namespace for a session - </refpurpose> - </refnamediv> - -<!-- body begins here --> - - <refsynopsisdiv> - <cmdsynopsis id="pam_namespace-cmdsynopsis"> - <command>pam_namespace.so</command> - <arg choice="opt"> - debug - </arg> - <arg choice="opt"> - unmnt_remnt - </arg> - <arg choice="opt"> - unmnt_only - </arg> - <arg choice="opt"> - require_selinux - </arg> - <arg choice="opt"> - gen_hash - </arg> - <arg choice="opt"> - ignore_config_error - </arg> - <arg choice="opt"> - ignore_instance_parent_mode - </arg> - <arg choice="opt"> - no_unmount_on_close - </arg> - <arg choice="opt"> - use_current_context - </arg> - <arg choice="opt"> - use_default_context - </arg> - </cmdsynopsis> - </refsynopsisdiv> - - - <refsect1 id="pam_namespace-description"> - <title>DESCRIPTION</title> - <para> - The pam_namespace PAM module sets up a private namespace for a session - with polyinstantiated directories. A polyinstantiated directory - provides a different instance of itself based on user name, or when - using SELinux, user name, security context or both. If an executable - script <filename>/etc/security/namespace.init</filename> exists, it - is used to initialize the namespace every time a new instance - directory is setup. The script receives the polyinstantiated - directory path, the instance directory path, flag whether the instance - directory was newly created (0 for no, 1 for yes), and the user name - as its arguments. - </para> - - <para> - The pam_namespace module disassociates the session namespace from - the parent namespace. Any mounts/unmounts performed in the parent - namespace, such as mounting of devices, are not reflected in the - session namespace. To propagate selected mount/unmount events from - the parent namespace into the disassociated session namespace, an - administrator may use the special shared-subtree feature. For - additional information on shared-subtree feature, please refer to - the mount(8) man page and the shared-subtree description at - http://lwn.net/Articles/159077 and http://lwn.net/Articles/159092. - </para> - - </refsect1> - - <refsect1 id="pam_namespace-options"> - <title>OPTIONS</title> - <variablelist> - - <varlistentry> - <term> - <option>debug</option> - </term> - <listitem> - <para> - A lot of debug information is logged using syslog - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>unmnt_remnt</option> - </term> - <listitem> - <para> - For programs such as su and newrole, the login - session has already setup a polyinstantiated - namespace. For these programs, polyinstantiation - is performed based on new user id or security - context, however the command first needs to - undo the polyinstantiation performed by login. - This argument instructs the command to - first undo previous polyinstantiation before - proceeding with new polyinstantiation based on - new id/context - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>unmnt_only</option> - </term> - <listitem> - <para> - For trusted programs that want to undo any - existing bind mounts and process instance - directories on their own, this argument allows - them to unmount currently mounted instance - directories - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>require_selinux</option> - </term> - <listitem> - <para> - If selinux is not enabled, return failure - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>gen_hash</option> - </term> - <listitem> - <para> - Instead of using the security context string - for the instance name, generate and use its - md5 hash. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>ignore_config_error</option> - </term> - <listitem> - <para> - If a line in the configuration file corresponding - to a polyinstantiated directory contains format - error, skip that line process the next line. - Without this option, pam will return an error - to the calling program resulting in termination - of the session. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>ignore_instance_parent_mode</option> - </term> - <listitem> - <para> - Instance parent directories by default are expected to have - the restrictive mode of 000. Using this option, an administrator - can choose to ignore the mode of the instance parent. This option - should be used with caution as it will reduce security and - isolation goals of the polyinstantiation mechanism. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>no_unmount_on_close</option> - </term> - <listitem> - <para> - For certain trusted programs such as newrole, open session - is called from a child process while the parent perfoms - close session and pam end functions. For these commands - use this option to instruct pam_close_session to not - unmount the bind mounted polyinstantiated directory in the - parent. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>use_current_context</option> - </term> - <listitem> - <para> - Useful for services which do not change the SELinux context - with setexeccon call. The module will use the current SELinux - context of the calling process for the level and context - polyinstantiation. - </para> - </listitem> - </varlistentry> - - <varlistentry> - <term> - <option>use_default_context</option> - </term> - <listitem> - <para> - Useful for services which do not use pam_selinux for changing - the SELinux context with setexeccon call. The module will use - the default SELinux context of the user for the level and context - polyinstantiation. - </para> - </listitem> - </varlistentry> - - </variablelist> - </refsect1> - - <refsect1 id="pam_namespace-services"> - <title>MODULE SERVICES PROVIDED</title> - <para> - The <option>session</option> service is supported. The module must not - be called from multithreaded processes. - </para> - </refsect1> - - <refsect1 id="pam_namespace-return_values"> - <title>RETURN VALUES</title> - <variablelist> - <varlistentry> - <term>PAM_SUCCESS</term> - <listitem> - <para> - Namespace setup was successful. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>PAM_SERVICE_ERR</term> - <listitem> - <para> - Unexpected system error occurred while setting up namespace. - </para> - </listitem> - </varlistentry> - <varlistentry> - <term>PAM_SESSION_ERR</term> - <listitem> - <para> - Unexpected namespace configuration error occurred. - </para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1 id="pam_namespace-files"> - <title>FILES</title> - <variablelist> - <varlistentry> - <term><filename>/etc/security/namespace.conf</filename></term> - <listitem> - <para>Main configuration file</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><filename>/etc/security/namespace.d</filename></term> - <listitem> - <para>Directory for additional configuration files</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><filename>/etc/security/namespace.init</filename></term> - <listitem> - <para>Init script for instance directories</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1 id="pam_namespace-examples"> - <title>EXAMPLES</title> - - <para> - For the <service>s you need polyinstantiation (login for example) - put the following line in /etc/pam.d/<service> as the last line for - session group: - </para> - - <para> - session required pam_namespace.so [arguments] - </para> - - <para> - To use polyinstantiation with graphical display manager gdm, insert the - following line, before exit 0, in /etc/gdm/PostSession/Default: - </para> - - <para> - /usr/sbin/gdm-safe-restart - </para> - - <para> - This allows gdm to restart after each session and appropriately adjust - namespaces of display manager and the X server. If polyinstantiation - of /tmp is desired along with the graphical environment, then additional - configuration changes are needed to address the interaction of X server - and font server namespaces with their use of /tmp to create - communication sockets. Please use the initialization script - <filename>/etc/security/namespace.init</filename> to ensure that - the X server and its clients can appropriately access the - communication socket X0. Please refer to the sample instructions - provided in the comment section of the instance initialization script - <filename>/etc/security/namespace.init</filename>. In addition, - perform the following changes to use graphical environment with - polyinstantiation of /tmp: - </para> - - <para> - <literallayout> - 1. Disable the use of font server by commenting out "FontPath" - line in /etc/X11/xorg.conf. If you do want to use the font server - then you will have to augment the instance initialization - script to appropriately provide /tmp/.font-unix from the - polyinstantiated /tmp. - 2. Ensure that the gdm service is setup to use pam_namespace, - as described above, by modifying /etc/pam.d/gdm. - 3. Ensure that the display manager is configured to restart X server - with each new session. This default setup can be verified by - making sure that /usr/share/gdm/defaults.conf contains - "AlwaysRestartServer=true", and it is not overridden by - /etc/gdm/custom.conf. - </literallayout> - </para> - - </refsect1> - - <refsect1 id="pam_namespace-see_also"> - <title>SEE ALSO</title> - <para> - <citerefentry> - <refentrytitle>namespace.conf</refentrytitle><manvolnum>5</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>pam.d</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>, - <citerefentry> - <refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum> - </citerefentry>. - </para> - </refsect1> - - <refsect1 id="pam_namespace-authors"> - <title>AUTHORS</title> - <para> - The namespace setup scheme was designed by Stephen Smalley, Janak Desai - and Chad Sellers. - The pam_namespace PAM module was developed by Janak Desai <janak@us.ibm.com>, - Chad Sellers <csellers@tresys.com> and Steve Grubb <sgrubb@redhat.com>. - Additional improvements by Xavier Toth <txtoth@gmail.com> and Tomas Mraz - <tmraz@redhat.com>. - </para> - </refsect1> -</refentry> diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c deleted file mode 100644 index d0741fd2..00000000 --- a/modules/pam_namespace/pam_namespace.c +++ /dev/null @@ -1,1907 +0,0 @@ -/****************************************************************************** - * A module for Linux-PAM that will set the default namespace after - * establishing a session via PAM. - * - * (C) Copyright IBM Corporation 2005 - * (C) Copyright Red Hat, Inc. 2006, 2008 - * All Rights Reserved. - * - * Written by: Janak Desai <janak@us.ibm.com> - * With Revisions by: Steve Grubb <sgrubb@redhat.com> - * Contributions by: Xavier Toth <txtoth@gmail.com>, - * Tomas Mraz <tmraz@redhat.com> - * Derived from a namespace setup patch by Chad Sellers <cdselle@tycho.nsa.gov> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "pam_namespace.h" -#include "argv_parse.h" - -/* - * Adds an entry for a polyinstantiated directory to the linked list of - * polyinstantiated directories. It is called from process_line() while - * parsing the namespace configuration file. - */ -static void add_polydir_entry(struct instance_data *idata, - struct polydir_s *ent) -{ - /* Now attach to linked list */ - ent->next = NULL; - if (idata->polydirs_ptr == NULL) - idata->polydirs_ptr = ent; - else { - struct polydir_s *tail; - - tail = idata->polydirs_ptr; - while (tail->next) - tail = tail->next; - tail->next = ent; - } -} - -static void del_polydir(struct polydir_s *poly) -{ - free(poly->uid); - free(poly->init_script); - free(poly); -} - -/* - * Deletes all the entries in the linked list. - */ -static void del_polydir_list(struct polydir_s *polydirs_ptr) -{ - struct polydir_s *dptr = polydirs_ptr; - - while (dptr) { - struct polydir_s *tptr = dptr; - dptr = dptr->next; - del_polydir(tptr); - } -} - -static void cleanup_data(pam_handle_t *pamh UNUSED , void *data, int err UNUSED) -{ - del_polydir_list(data); -} - -static char *expand_variables(const char *orig, const char *var_names[], const char *var_values[]) -{ - const char *src = orig; - char *dst; - char *expanded; - char c; - size_t dstlen = 0; - while (*src) { - if (*src == '$') { - int i; - for (i = 0; var_names[i]; i++) { - int namelen = strlen(var_names[i]); - if (strncmp(var_names[i], src+1, namelen) == 0) { - dstlen += strlen(var_values[i]) - 1; /* $ */ - src += namelen; - break; - } - } - } - ++dstlen; - ++src; - } - if ((dst=expanded=malloc(dstlen + 1)) == NULL) - return NULL; - src = orig; - while ((c=*src) != '\0') { - if (c == '$') { - int i; - for (i = 0; var_names[i]; i++) { - int namelen = strlen(var_names[i]); - if (strncmp(var_names[i], src+1, namelen) == 0) { - dst = stpcpy(dst, var_values[i]); - --dst; - c = *dst; /* replace $ */ - src += namelen; - break; - } - } - } - *dst = c; - ++dst; - ++src; - } - *dst = '\0'; - return expanded; -} - -static int parse_create_params(char *params, struct polydir_s *poly) -{ - char *sptr; - struct passwd *pwd; - struct group *grp; - - poly->mode = (mode_t)ULONG_MAX; - poly->owner = (uid_t)ULONG_MAX; - poly->group = (gid_t)ULONG_MAX; - - if (*params != '=') - return 0; - params++; - - params = strtok_r(params, ",", &sptr); - if (params == NULL) - return 0; - - errno = 0; - poly->mode = (mode_t)strtoul(params, NULL, 0); - if (errno != 0) { - poly->mode = (mode_t)ULONG_MAX; - } - - params = strtok_r(NULL, ",", &sptr); - if (params == NULL) - return 0; - - pwd = getpwnam(params); /* session modules are not reentrant */ - if (pwd == NULL) - return -1; - poly->owner = pwd->pw_uid; - - params = strtok_r(NULL, ",", &sptr); - if (params == NULL) { - poly->group = pwd->pw_gid; - return 0; - } - grp = getgrnam(params); - if (grp == NULL) - return -1; - poly->group = grp->gr_gid; - - return 0; -} - -static int parse_iscript_params(char *params, struct polydir_s *poly) -{ - if (*params != '=') - return 0; - params++; - - if (*params != '\0') { - if (*params != '/') { /* path is relative to NAMESPACE_D_DIR */ - if (asprintf(&poly->init_script, "%s%s", NAMESPACE_D_DIR, params) == -1) - return -1; - } else { - poly->init_script = strdup(params); - } - if (poly->init_script == NULL) - return -1; - } - return 0; -} - -static int parse_method(char *method, struct polydir_s *poly, - struct instance_data *idata) -{ - enum polymethod pm; - char *sptr; - static const char *method_names[] = { "user", "context", "level", "tmpdir", - "tmpfs", NULL }; - static const char *flag_names[] = { "create", "noinit", "iscript", - "shared", NULL }; - static const unsigned int flag_values[] = { POLYDIR_CREATE, POLYDIR_NOINIT, - POLYDIR_ISCRIPT, POLYDIR_SHARED }; - int i; - char *flag; - - method = strtok_r(method, ":", &sptr); - pm = NONE; - - for (i = 0; method_names[i]; i++) { - if (strcmp(method, method_names[i]) == 0) { - pm = i + 1; /* 0 = NONE */ - } - } - - if (pm == NONE) { - pam_syslog(idata->pamh, LOG_NOTICE, "Unknown method"); - return -1; - } - - poly->method = pm; - - while ((flag=strtok_r(NULL, ":", &sptr)) != NULL) { - for (i = 0; flag_names[i]; i++) { - int namelen = strlen(flag_names[i]); - - if (strncmp(flag, flag_names[i], namelen) == 0) { - poly->flags |= flag_values[i]; - switch (flag_values[i]) { - case POLYDIR_CREATE: - if (parse_create_params(flag+namelen, poly) != 0) { - pam_syslog(idata->pamh, LOG_CRIT, "Invalid create parameters"); - return -1; - } - break; - - case POLYDIR_ISCRIPT: - if (parse_iscript_params(flag+namelen, poly) != 0) { - pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error"); - return -1; - }; - break; - } - } - } - } - - return 0; -} - -/* - * Called from parse_config_file, this function processes a single line - * of the namespace configuration file. It skips over comments and incomplete - * or malformed lines. It processes a valid line with information on - * polyinstantiating a directory by populating appropriate fields of a - * polyinstatiated directory structure and then calling add_polydir_entry to - * add that entry to the linked list of polyinstantiated directories. - */ -static int process_line(char *line, const char *home, const char *rhome, - struct instance_data *idata) -{ - char *dir = NULL, *instance_prefix = NULL, *rdir = NULL; - char *method, *uids; - char *tptr; - struct polydir_s *poly; - int retval = 0; - char **config_options = NULL; - static const char *var_names[] = {"HOME", "USER", NULL}; - const char *var_values[] = {home, idata->user}; - const char *rvar_values[] = {rhome, idata->ruser}; - int len; - - poly = calloc(1, sizeof(*poly)); - if (poly == NULL) - goto erralloc; - - /* - * skip the leading white space - */ - while (*line && isspace(*line)) - line++; - - /* - * Rip off the comments - */ - tptr = strchr(line,'#'); - if (tptr) - *tptr = '\0'; - - /* - * Rip off the newline char - */ - tptr = strchr(line,'\n'); - if (tptr) - *tptr = '\0'; - - /* - * Anything left ? - */ - if (line[0] == 0) - return 0; - - /* - * Initialize and scan the five strings from the line from the - * namespace configuration file. - */ - retval = argv_parse(line, NULL, &config_options); - if (retval != 0) { - goto erralloc; - } - - dir = config_options[0]; - if (dir == NULL) { - pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing polydir"); - goto skipping; - } - instance_prefix = config_options[1]; - if (instance_prefix == NULL) { - pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing instance_prefix"); - instance_prefix = NULL; - goto skipping; - } - method = config_options[2]; - if (method == NULL) { - pam_syslog(idata->pamh, LOG_NOTICE, "Invalid line missing method"); - instance_prefix = NULL; - dir = NULL; - goto skipping; - } - - /* - * Only the uids field is allowed to be blank, to indicate no - * override users for polyinstantiation of that directory. If - * any of the other fields are blank, the line is incomplete so - * skip it. - */ - uids = config_options[3]; - - /* - * Expand $HOME and $USER in poly dir and instance dir prefix - */ - if ((rdir=expand_variables(dir, var_names, rvar_values)) == NULL) { - instance_prefix = NULL; - dir = NULL; - goto erralloc; - } - - if ((dir=expand_variables(dir, var_names, var_values)) == NULL) { - instance_prefix = NULL; - goto erralloc; - } - - if ((instance_prefix=expand_variables(instance_prefix, var_names, var_values)) - == NULL) { - goto erralloc; - } - - if (idata->flags & PAMNS_DEBUG) { - pam_syslog(idata->pamh, LOG_DEBUG, "Expanded polydir: '%s'", dir); - pam_syslog(idata->pamh, LOG_DEBUG, "Expanded ruser polydir: '%s'", rdir); - pam_syslog(idata->pamh, LOG_DEBUG, "Expanded instance prefix: '%s'", instance_prefix); - } - - len = strlen(dir); - if (len > 0 && dir[len-1] == '/') { - dir[len-1] = '\0'; - } - - len = strlen(rdir); - if (len > 0 && rdir[len-1] == '/') { - rdir[len-1] = '\0'; - } - - if (dir[0] == '\0' || rdir[0] == '\0') { - pam_syslog(idata->pamh, LOG_NOTICE, "Invalid polydir"); - goto skipping; - } - - /* - * Populate polyinstantiated directory structure with appropriate - * pathnames and the method with which to polyinstantiate. - */ - if (strlen(dir) >= sizeof(poly->dir) - || strlen(rdir) >= sizeof(poly->rdir) - || strlen(instance_prefix) >= sizeof(poly->instance_prefix)) { - pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long"); - goto skipping; - } - strcpy(poly->dir, dir); - strcpy(poly->rdir, rdir); - strcpy(poly->instance_prefix, instance_prefix); - - if (parse_method(method, poly, idata) != 0) { - goto skipping; - } - - if (poly->method == TMPDIR) { - if (sizeof(poly->instance_prefix) - strlen(poly->instance_prefix) < 7) { - pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames too long"); - goto skipping; - } - strcat(poly->instance_prefix, "XXXXXX"); - } - - /* - * Ensure that all pathnames are absolute path names. - */ - if ((poly->dir[0] != '/') || (poly->method != TMPFS && poly->instance_prefix[0] != '/')) { - pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must start with '/'"); - goto skipping; - } - if (strstr(dir, "..") || strstr(poly->instance_prefix, "..")) { - pam_syslog(idata->pamh, LOG_NOTICE, "Pathnames must not contain '..'"); - goto skipping; - } - - /* - * If the line in namespace.conf for a directory to polyinstantiate - * contains a list of override users (users for whom polyinstantiation - * is not performed), read the user ids, convert names into uids, and - * add to polyinstantiated directory structure. - */ - if (uids) { - uid_t *uidptr; - const char *ustr, *sstr; - int count, i; - - if (*uids == '~') { - poly->flags |= POLYDIR_EXCLUSIVE; - uids++; - } - for (count = 0, ustr = sstr = uids; sstr; ustr = sstr + 1, count++) - sstr = strchr(ustr, ','); - - poly->num_uids = count; - poly->uid = (uid_t *) malloc(count * sizeof (uid_t)); - uidptr = poly->uid; - if (uidptr == NULL) { - goto erralloc; - } - - ustr = uids; - for (i = 0; i < count; i++) { - struct passwd *pwd; - - tptr = strchr(ustr, ','); - if (tptr) - *tptr = '\0'; - - pwd = pam_modutil_getpwnam(idata->pamh, ustr); - if (pwd == NULL) { - pam_syslog(idata->pamh, LOG_ERR, "Unknown user %s in configuration", ustr); - poly->num_uids--; - } else { - *uidptr = pwd->pw_uid; - uidptr++; - } - ustr = tptr + 1; - } - } - - /* - * Add polyinstantiated directory structure to the linked list - * of all polyinstantiated directory structures. - */ - add_polydir_entry(idata, poly); - - goto out; - -erralloc: - pam_syslog(idata->pamh, LOG_CRIT, "Memory allocation error"); - -skipping: - if (idata->flags & PAMNS_IGN_CONFIG_ERR) - retval = 0; - else - retval = PAM_SERVICE_ERR; - del_polydir(poly); -out: - free(rdir); - free(dir); - free(instance_prefix); - argv_free(config_options); - return retval; -} - - -/* - * Parses /etc/security/namespace.conf file to build a linked list of - * polyinstantiated directory structures of type polydir_s. Each entry - * in the linked list contains information needed to polyinstantiate - * one directory. - */ -static int parse_config_file(struct instance_data *idata) -{ - FILE *fil; - char *home, *rhome; - const char *confname; - struct passwd *cpwd; - char *line; - int retval; - size_t len = 0; - glob_t globbuf; - const char *oldlocale; - size_t n; - - /* - * Extract the user's home directory to resolve $HOME entries - * in the namespace configuration file. - */ - cpwd = pam_modutil_getpwnam(idata->pamh, idata->user); - if (!cpwd) { - pam_syslog(idata->pamh, LOG_ERR, - "Error getting home dir for '%s'", idata->user); - return PAM_SESSION_ERR; - } - if ((home=strdup(cpwd->pw_dir)) == NULL) { - pam_syslog(idata->pamh, LOG_CRIT, - "Memory allocation error"); - return PAM_SESSION_ERR; - } - - cpwd = pam_modutil_getpwnam(idata->pamh, idata->ruser); - if (!cpwd) { - pam_syslog(idata->pamh, LOG_ERR, - "Error getting home dir for '%s'", idata->ruser); - free(home); - return PAM_SESSION_ERR; - } - - if ((rhome=strdup(cpwd->pw_dir)) == NULL) { - pam_syslog(idata->pamh, LOG_CRIT, - "Memory allocation error"); - free(home); - return PAM_SESSION_ERR; - } - - /* - * Open configuration file, read one line at a time and call - * process_line to process each line. - */ - - memset(&globbuf, '\0', sizeof(globbuf)); - oldlocale = setlocale(LC_COLLATE, "C"); - glob(NAMESPACE_D_GLOB, 0, NULL, &globbuf); - if (oldlocale != NULL) - setlocale(LC_COLLATE, oldlocale); - - confname = PAM_NAMESPACE_CONFIG; - n = 0; - for (;;) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "Parsing config file %s", - confname); - fil = fopen(confname, "r"); - if (fil == NULL) { - pam_syslog(idata->pamh, LOG_ERR, "Error opening config file %s", - confname); - globfree(&globbuf); - free(rhome); - free(home); - return PAM_SERVICE_ERR; - } - - /* Use unlocked IO */ - __fsetlocking(fil, FSETLOCKING_BYCALLER); - - line = NULL; - /* loop reading the file */ - while (getline(&line, &len, fil) > 0) { - retval = process_line(line, home, rhome, idata); - if (retval) { - pam_syslog(idata->pamh, LOG_ERR, - "Error processing conf file %s line %s", confname, line); - fclose(fil); - free(line); - globfree(&globbuf); - free(rhome); - free(home); - return PAM_SERVICE_ERR; - } - } - fclose(fil); - free(line); - - if (n >= globbuf.gl_pathc) - break; - - confname = globbuf.gl_pathv[n]; - n++; - } - - globfree(&globbuf); - free(rhome); - free(home); - - /* All done...just some debug stuff */ - if (idata->flags & PAMNS_DEBUG) { - struct polydir_s *dptr = idata->polydirs_ptr; - uid_t *iptr; - uid_t i; - - pam_syslog(idata->pamh, LOG_DEBUG, - dptr?"Configured poly dirs:":"No configured poly dirs"); - while (dptr) { - pam_syslog(idata->pamh, LOG_DEBUG, "dir='%s' iprefix='%s' meth=%d", - dptr->dir, dptr->instance_prefix, dptr->method); - for (i = 0, iptr = dptr->uid; i < dptr->num_uids; i++, iptr++) - pam_syslog(idata->pamh, LOG_DEBUG, "override user %d ", *iptr); - dptr = dptr->next; - } - } - - return PAM_SUCCESS; -} - - -/* - * This funtion returns true if a given uid is present in the polyinstantiated - * directory's list of override uids. If the uid is one of the override - * uids for the polyinstantiated directory, polyinstantiation is not - * performed for that user for that directory. - * If exclusive is set the returned values are opposite. - */ -static int ns_override(struct polydir_s *polyptr, struct instance_data *idata, - uid_t uid) -{ - unsigned int i; - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Checking for ns override in dir %s for uid %d", - polyptr->dir, uid); - - for (i = 0; i < polyptr->num_uids; i++) { - if (uid == polyptr->uid[i]) { - return !(polyptr->flags & POLYDIR_EXCLUSIVE); - } - } - - return !!(polyptr->flags & POLYDIR_EXCLUSIVE); -} - -/* - * md5hash generates a hash of the passed in instance directory name. - */ -static char *md5hash(const char *instname, struct instance_data *idata) -{ - int i; - char *md5inst = NULL; - char *to; - unsigned char inst_digest[MD5_DIGEST_LENGTH]; - - /* - * Create MD5 hashes for instance pathname. - */ - - MD5((const unsigned char *)instname, strlen(instname), inst_digest); - - if ((md5inst = malloc(MD5_DIGEST_LENGTH * 2 + 1)) == NULL) { - pam_syslog(idata->pamh, LOG_ERR, "Unable to allocate buffer"); - return NULL; - } - - to = md5inst; - for (i = 0; i < MD5_DIGEST_LENGTH; i++) { - snprintf(to, 3, "%02x", (unsigned int)inst_digest[i]); - to += 2; - } - - return md5inst; -} - -#ifdef WITH_SELINUX -static int form_context(const struct polydir_s *polyptr, - security_context_t *i_context, security_context_t *origcon, - struct instance_data *idata) -{ - int rc = PAM_SUCCESS; - security_context_t scon = NULL; - security_class_t tclass; - - /* - * Get the security context of the directory to polyinstantiate. - */ - rc = getfilecon(polyptr->dir, origcon); - if (rc < 0 || *origcon == NULL) { - pam_syslog(idata->pamh, LOG_ERR, - "Error getting poly dir context, %m"); - return PAM_SESSION_ERR; - } - - if (polyptr->method == USER) return PAM_SUCCESS; - - if (idata->flags & PAMNS_USE_CURRENT_CONTEXT) { - rc = getcon(&scon); - } else if (idata->flags & PAMNS_USE_DEFAULT_CONTEXT) { - char *seuser = NULL, *level = NULL; - - if ((rc=getseuserbyname(idata->user, &seuser, &level)) == 0) { - rc = get_default_context_with_level(seuser, level, NULL, &scon); - free(seuser); - free(level); - } - } else { - rc = getexeccon(&scon); - } - if (rc < 0 || scon == NULL) { - pam_syslog(idata->pamh, LOG_ERR, - "Error getting exec context, %m"); - return PAM_SESSION_ERR; - } - - /* - * If polyinstantiating based on security context, get current - * process security context, get security class for directories, - * and ask the policy to provide security context of the - * polyinstantiated instance directory. - */ - - if (polyptr->method == CONTEXT) { - tclass = string_to_security_class("dir"); - - if (security_compute_member(scon, *origcon, tclass, - i_context) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error computing poly dir member context"); - freecon(scon); - return PAM_SESSION_ERR; - } else if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "member context returned by policy %s", *i_context); - freecon(scon); - return PAM_SUCCESS; - } - - /* - * If polyinstantiating based on security level, get current - * process security context, get security class for directories, - * and change the directories MLS Level to match process. - */ - - if (polyptr->method == LEVEL) { - context_t scontext = NULL; - context_t fcontext = NULL; - rc = PAM_SESSION_ERR; - - scontext = context_new(scon); - if (! scontext) { - pam_syslog(idata->pamh, LOG_ERR, "out of memory"); - goto fail; - } - fcontext = context_new(*origcon); - if (! fcontext) { - pam_syslog(idata->pamh, LOG_ERR, "out of memory"); - goto fail; - } - if (context_range_set(fcontext, context_range_get(scontext)) != 0) { - pam_syslog(idata->pamh, LOG_ERR, "Unable to set MLS Componant of context"); - goto fail; - } - *i_context=strdup(context_str(fcontext)); - if (! *i_context) { - pam_syslog(idata->pamh, LOG_ERR, "out of memory"); - goto fail; - } - - rc = PAM_SUCCESS; - fail: - context_free(scontext); - context_free(fcontext); - freecon(scon); - return rc; - } - /* Should never get here */ - return PAM_SUCCESS; -} -#endif - -/* - * poly_name returns the name of the polyinstantiated instance directory - * based on the method used for polyinstantiation (user, context or level) - * In addition, the function also returns the security contexts of the - * original directory to polyinstantiate and the polyinstantiated instance - * directory. - */ -#ifdef WITH_SELINUX -static int poly_name(const struct polydir_s *polyptr, char **i_name, - security_context_t *i_context, security_context_t *origcon, - struct instance_data *idata) -#else -static int poly_name(const struct polydir_s *polyptr, char **i_name, - struct instance_data *idata) -#endif -{ - int rc; - char *hash = NULL; - enum polymethod pm; -#ifdef WITH_SELINUX - security_context_t rawcon = NULL; -#endif - - *i_name = NULL; -#ifdef WITH_SELINUX - *i_context = NULL; - *origcon = NULL; - if ((idata->flags & PAMNS_SELINUX_ENABLED) && - (rc=form_context(polyptr, i_context, origcon, idata)) != PAM_SUCCESS) { - return rc; - } -#endif - - rc = PAM_SESSION_ERR; - /* - * Set the name of the polyinstantiated instance dir based on the - * polyinstantiation method. - */ - - pm = polyptr->method; - if (pm == LEVEL || pm == USER) { -#ifdef WITH_SELINUX - if (!(idata->flags & PAMNS_CTXT_BASED_INST)) -#else - pam_syslog(idata->pamh, LOG_NOTICE, - "Context and level methods not available, using user method"); -#endif - if (polyptr->flags & POLYDIR_SHARED) { - rc = PAM_IGNORE; - goto fail; - } - pm = USER; - } - - switch (pm) { - case USER: - if (asprintf(i_name, "%s", idata->user) < 0) { - *i_name = NULL; - goto fail; - } - break; - -#ifdef WITH_SELINUX - case LEVEL: - case CONTEXT: - if (selinux_trans_to_raw_context(*i_context, &rawcon) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error translating directory context"); - goto fail; - } - if (polyptr->flags & POLYDIR_SHARED) { - if (asprintf(i_name, "%s", rawcon) < 0) { - *i_name = NULL; - goto fail; - } - } else { - if (asprintf(i_name, "%s_%s", rawcon, idata->user) < 0) { - *i_name = NULL; - goto fail; - } - } - break; - -#endif /* WITH_SELINUX */ - - case TMPDIR: - case TMPFS: - if ((*i_name=strdup("")) == NULL) - goto fail; - return PAM_SUCCESS; - - default: - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_ERR, "Unknown method"); - goto fail; - } - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "poly_name %s", *i_name); - - if ((idata->flags & PAMNS_GEN_HASH) || strlen(*i_name) > NAMESPACE_MAX_DIR_LEN) { - hash = md5hash(*i_name, idata); - if (hash == NULL) { - goto fail; - } - if (idata->flags & PAMNS_GEN_HASH) { - free(*i_name); - *i_name = hash; - hash = NULL; - } else { - char *newname; - if (asprintf(&newname, "%.*s_%s", NAMESPACE_MAX_DIR_LEN-1-(int)strlen(hash), - *i_name, hash) < 0) { - goto fail; - } - free(*i_name); - *i_name = newname; - } - } - rc = PAM_SUCCESS; - -fail: - free(hash); -#ifdef WITH_SELINUX - freecon(rawcon); -#endif - if (rc != PAM_SUCCESS) { -#ifdef WITH_SELINUX - freecon(*i_context); - *i_context = NULL; - freecon(*origcon); - *origcon = NULL; -#endif - free(*i_name); - *i_name = NULL; - } - return rc; -} - -static int check_inst_parent(char *ipath, struct instance_data *idata) -{ - struct stat instpbuf; - char *inst_parent, *trailing_slash; - /* - * stat the instance parent path to make sure it exists - * and is a directory. Check that its mode is 000 (unless the - * admin explicitly instructs to ignore the instance parent - * mode by the "ignore_instance_parent_mode" argument). - */ - inst_parent = (char *) malloc(strlen(ipath)+1); - if (!inst_parent) { - pam_syslog(idata->pamh, LOG_ERR, "Error allocating pathname string"); - return PAM_SESSION_ERR; - } - - strcpy(inst_parent, ipath); - trailing_slash = strrchr(inst_parent, '/'); - if (trailing_slash) - *trailing_slash = '\0'; - - if (stat(inst_parent, &instpbuf) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", inst_parent); - free(inst_parent); - return PAM_SESSION_ERR; - } - - /* - * Make sure we are dealing with a directory - */ - if (!S_ISDIR(instpbuf.st_mode)) { - pam_syslog(idata->pamh, LOG_ERR, "Instance parent %s is not a dir", - inst_parent); - free(inst_parent); - return PAM_SESSION_ERR; - } - - if ((idata->flags & PAMNS_IGN_INST_PARENT_MODE) == 0) { - if (instpbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) { - pam_syslog(idata->pamh, LOG_ERR, "Mode of inst parent %s not 000", - inst_parent); - free(inst_parent); - return PAM_SESSION_ERR; - } - } - free(inst_parent); - return PAM_SUCCESS; -} - -/* -* Check to see if there is a namespace initialization script in -* the /etc/security directory. If such a script exists -* execute it and pass directory to polyinstantiate and instance -* directory as arguments. -*/ -static int inst_init(const struct polydir_s *polyptr, const char *ipath, - struct instance_data *idata, int newdir) -{ - pid_t rc, pid; - sighandler_t osighand = NULL; - int status; - const char *init_script = NAMESPACE_INIT_SCRIPT; - - osighand = signal(SIGCHLD, SIG_DFL); - if (osighand == SIG_ERR) { - pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value"); - rc = PAM_SESSION_ERR; - goto out; - } - - if ((polyptr->flags & POLYDIR_ISCRIPT) && polyptr->init_script) - init_script = polyptr->init_script; - - if (access(init_script, F_OK) == 0) { - if (access(init_script, X_OK) < 0) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_ERR, - "Namespace init script not executable"); - rc = PAM_SESSION_ERR; - goto out; - } else { - pid = fork(); - if (pid == 0) { -#ifdef WITH_SELINUX - if (idata->flags & PAMNS_SELINUX_ENABLED) { - if (setexeccon(NULL) < 0) - exit(1); - } -#endif - if (execl(init_script, init_script, - polyptr->dir, ipath, newdir?"1":"0", idata->user, (char *)NULL) < 0) - exit(1); - } else if (pid > 0) { - while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && - (errno == EINTR)); - if (rc == (pid_t)-1) { - pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m"); - rc = PAM_SESSION_ERR; - goto out; - } - if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error initializing instance"); - rc = PAM_SESSION_ERR; - goto out; - } - } else if (pid < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Cannot fork to run namespace init script, %m"); - rc = PAM_SESSION_ERR; - goto out; - } - } - } - rc = PAM_SUCCESS; -out: - (void) signal(SIGCHLD, osighand); - - return rc; -} - -static int create_polydir(struct polydir_s *polyptr, - struct instance_data *idata) -{ - mode_t mode; - int rc; -#ifdef WITH_SELINUX - security_context_t dircon, oldcon = NULL; -#endif - const char *dir = polyptr->dir; - - if (polyptr->mode != (mode_t)ULONG_MAX) - mode = polyptr->mode; - else - mode = 0777; - -#ifdef WITH_SELINUX - if (idata->flags & PAMNS_SELINUX_ENABLED) { - getfscreatecon(&oldcon); - rc = matchpathcon(dir, S_IFDIR, &dircon); - if (rc) { - pam_syslog(idata->pamh, LOG_NOTICE, - "Unable to get default context for directory %s, check your policy: %m", dir); - } else { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Polydir %s context: %s", dir, (char *)dircon); - if (setfscreatecon(dircon) != 0) - pam_syslog(idata->pamh, LOG_NOTICE, - "Error setting context for directory %s: %m", dir); - freecon(dircon); - } - matchpathcon_fini(); - } -#endif - - rc = mkdir(dir, mode); - if (rc != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error creating directory %s: %m", dir); - return PAM_SESSION_ERR; - } - -#ifdef WITH_SELINUX - if (idata->flags & PAMNS_SELINUX_ENABLED) { - if (setfscreatecon(oldcon) != 0) - pam_syslog(idata->pamh, LOG_NOTICE, - "Error resetting fs create context: %m"); - freecon(oldcon); - } -#endif - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "Created polydir %s", dir); - - if (polyptr->mode != (mode_t)ULONG_MAX) { - /* explicit mode requested */ - if (chmod(dir, mode) != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error changing mode of directory %s: %m", dir); - rmdir(dir); - return PAM_SESSION_ERR; - } - } - - if (polyptr->owner != (uid_t)ULONG_MAX) { - if (chown(dir, polyptr->owner, polyptr->group) != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Unable to change owner on directory %s: %m", dir); - rmdir(dir); - return PAM_SESSION_ERR; - } - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Polydir owner %u group %u from configuration", polyptr->owner, polyptr->group); - } else { - if (chown(dir, idata->uid, idata->gid) != 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Unable to change owner on directory %s: %m", dir); - rmdir(dir); - return PAM_SESSION_ERR; - } - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Polydir owner %u group %u", idata->uid, idata->gid); - } - - return PAM_SUCCESS; -} - -/* - * Create polyinstantiated instance directory (ipath). - */ -#ifdef WITH_SELINUX -static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, - security_context_t icontext, security_context_t ocontext, - struct instance_data *idata) -#else -static int create_dirs(struct polydir_s *polyptr, char *ipath, struct stat *statbuf, - struct instance_data *idata) -#endif -{ - struct stat newstatbuf; - int fd; - int newdir = 0; - - /* - * Check to make sure instance parent is valid. - */ - if (check_inst_parent(ipath, idata)) - return PAM_SESSION_ERR; - - /* - * Create instance directory and set its security context to the context - * returned by the security policy. Set its mode and ownership - * attributes to match that of the original directory that is being - * polyinstantiated. - */ - - if (polyptr->method == TMPDIR) { - if (mkdtemp(polyptr->instance_prefix) == NULL) { - pam_syslog(idata->pamh, LOG_ERR, "Error creating temporary instance %s, %m", - polyptr->instance_prefix); - polyptr->method = NONE; /* do not clean up! */ - return PAM_SESSION_ERR; - } - /* copy the actual directory name to ipath */ - strcpy(ipath, polyptr->instance_prefix); - } else if (mkdir(ipath, S_IRUSR) < 0) { - if (errno == EEXIST) - goto inst_init; - else { - pam_syslog(idata->pamh, LOG_ERR, "Error creating %s, %m", - ipath); - return PAM_SESSION_ERR; - } - } - - newdir = 1; - /* Open a descriptor to it to prevent races */ - fd = open(ipath, O_DIRECTORY | O_RDONLY); - if (fd < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error opening %s, %m", ipath); - rmdir(ipath); - return PAM_SESSION_ERR; - } -#ifdef WITH_SELINUX - /* If SE Linux is disabled, no need to label it */ - if (idata->flags & PAMNS_SELINUX_ENABLED) { - /* If method is USER, icontext is NULL */ - if (icontext) { - if (fsetfilecon(fd, icontext) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error setting context of %s to %s", ipath, icontext); - close(fd); - rmdir(ipath); - return PAM_SESSION_ERR; - } - } else { - if (fsetfilecon(fd, ocontext) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error setting context of %s to %s", ipath, ocontext); - close(fd); - rmdir(ipath); - return PAM_SESSION_ERR; - } - } - } -#endif - if (fstat(fd, &newstatbuf) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", - ipath); - rmdir(ipath); - return PAM_SESSION_ERR; - } - if (newstatbuf.st_uid != statbuf->st_uid || - newstatbuf.st_gid != statbuf->st_gid) { - if (fchown(fd, statbuf->st_uid, statbuf->st_gid) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error changing owner for %s, %m", - ipath); - close(fd); - rmdir(ipath); - return PAM_SESSION_ERR; - } - } - if (fchmod(fd, statbuf->st_mode & 07777) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error changing mode for %s, %m", - ipath); - close(fd); - rmdir(ipath); - return PAM_SESSION_ERR; - } - close(fd); - - /* - * Check to see if there is a namespace initialization script in - * the /etc/security directory. If such a script exists - * execute it and pass directory to polyinstantiate and instance - * directory as arguments. - */ - -inst_init: - if (polyptr->flags & POLYDIR_NOINIT) - return PAM_SUCCESS; - - return inst_init(polyptr, ipath, idata, newdir); -} - - -/* - * This function performs the namespace setup for a particular directory - * that is being polyinstantiated. It creates an MD5 hash of instance - * directory, calls create_dirs to create it with appropriate - * security attributes, and performs bind mount to setup the process - * namespace. - */ -static int ns_setup(struct polydir_s *polyptr, - struct instance_data *idata) -{ - int retval = 0; - char *inst_dir = NULL; - char *instname = NULL; - struct stat statbuf; -#ifdef WITH_SELINUX - security_context_t instcontext = NULL, origcontext = NULL; -#endif - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Set namespace for directory %s", polyptr->dir); - - while (stat(polyptr->dir, &statbuf) < 0) { - if (retval || !(polyptr->flags & POLYDIR_CREATE)) { - pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", - polyptr->dir); - return PAM_SESSION_ERR; - } else { - if (create_polydir(polyptr, idata) != PAM_SUCCESS) - return PAM_SESSION_ERR; - retval = PAM_SESSION_ERR; /* bail out on next failed stat */ - } - } - - /* - * Make sure we are dealing with a directory - */ - if (!S_ISDIR(statbuf.st_mode)) { - pam_syslog(idata->pamh, LOG_ERR, "Polydir %s is not a dir", - polyptr->dir); - return PAM_SESSION_ERR; - } - - if (polyptr->method == TMPFS) { - if (mount("tmpfs", polyptr->dir, "tmpfs", 0, NULL) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error mounting tmpfs on %s, %m", - polyptr->dir); - return PAM_SESSION_ERR; - } - /* we must call inst_init after the mount in this case */ - return inst_init(polyptr, "tmpfs", idata, 1); - } - - /* - * Obtain the name of instance pathname based on the - * polyinstantiation method and instance context returned by - * security policy. - */ -#ifdef WITH_SELINUX - retval = poly_name(polyptr, &instname, &instcontext, - &origcontext, idata); -#else - retval = poly_name(polyptr, &instname, idata); -#endif - - if (retval != PAM_SUCCESS) { - if (retval != PAM_IGNORE) - pam_syslog(idata->pamh, LOG_ERR, "Error getting instance name"); - goto cleanup; - } else { -#ifdef WITH_SELINUX - if ((idata->flags & PAMNS_DEBUG) && - (idata->flags & PAMNS_SELINUX_ENABLED)) - pam_syslog(idata->pamh, LOG_DEBUG, "Inst ctxt %s Orig ctxt %s", - instcontext, origcontext); -#endif - } - - if (asprintf(&inst_dir, "%s%s", polyptr->instance_prefix, instname) < 0) - goto error_out; - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "instance_dir %s", - inst_dir); - - /* - * Create instance directory with appropriate security - * contexts, owner, group and mode bits. - */ -#ifdef WITH_SELINUX - retval = create_dirs(polyptr, inst_dir, &statbuf, instcontext, - origcontext, idata); -#else - retval = create_dirs(polyptr, inst_dir, &statbuf, idata); -#endif - - if (retval < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error creating instance dir"); - goto error_out; - } - - /* - * Bind mount instance directory on top of the polyinstantiated - * directory to provide an instance of polyinstantiated directory - * based on polyinstantiated method. - */ - if (mount(inst_dir, polyptr->dir, NULL, MS_BIND, NULL) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Error mounting %s on %s, %m", - inst_dir, polyptr->dir); - goto error_out; - } - - goto cleanup; - - /* - * various error exit points. Free allocated memory and set return - * value to indicate a pam session error. - */ -error_out: - retval = PAM_SESSION_ERR; - -cleanup: - free(inst_dir); - free(instname); -#ifdef WITH_SELINUX - freecon(instcontext); - freecon(origcontext); -#endif - return retval; -} - - -/* - * This function checks to see if the current working directory is - * inside the directory passed in as the first argument. - */ -static int cwd_in(char *dir, struct instance_data *idata) -{ - int retval = 0; - char cwd[PATH_MAX]; - - if (getcwd(cwd, PATH_MAX) == NULL) { - pam_syslog(idata->pamh, LOG_ERR, "Can't get current dir, %m"); - return -1; - } - - if (strncmp(cwd, dir, strlen(dir)) == 0) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "cwd is inside %s", dir); - retval = 1; - } else { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "cwd is outside %s", dir); - } - - return retval; -} - -static int cleanup_tmpdirs(struct instance_data *idata) -{ - struct polydir_s *pptr; - pid_t rc, pid; - sighandler_t osighand = NULL; - int status; - - osighand = signal(SIGCHLD, SIG_DFL); - if (osighand == SIG_ERR) { - pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value"); - rc = PAM_SESSION_ERR; - goto out; - } - - for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (pptr->method == TMPDIR && access(pptr->instance_prefix, F_OK) == 0) { - pid = fork(); - if (pid == 0) { -#ifdef WITH_SELINUX - if (idata->flags & PAMNS_SELINUX_ENABLED) { - if (setexeccon(NULL) < 0) - exit(1); - } -#endif - if (execl("/bin/rm", "/bin/rm", "-rf", pptr->instance_prefix, (char *)NULL) < 0) - exit(1); - } else if (pid > 0) { - while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) && - (errno == EINTR)); - if (rc == (pid_t)-1) { - pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m"); - rc = PAM_SESSION_ERR; - goto out; - } - if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Error removing %s", pptr->instance_prefix); - } - } else if (pid < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Cannot fork to run namespace init script, %m"); - rc = PAM_SESSION_ERR; - goto out; - } - } - } - - rc = PAM_SUCCESS; -out: - signal(SIGCHLD, osighand); - return rc; -} - -/* - * This function checks to see if polyinstantiation is needed for any - * of the directories listed in the configuration file. If needed, - * cycles through all polyinstantiated directory entries and calls - * ns_setup to setup polyinstantiation for each one of them. - */ -static int setup_namespace(struct instance_data *idata, enum unmnt_op unmnt) -{ - int retval = 0, need_poly = 0, changing_dir = 0; - char *cptr, *fptr, poly_parent[PATH_MAX]; - struct polydir_s *pptr; - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "Set up namespace for pid %d", - getpid()); - - /* - * Cycle through all polyinstantiated directory entries to see if - * polyinstantiation is needed at all. - */ - for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (ns_override(pptr, idata, idata->uid)) { - if (unmnt == NO_UNMNT || ns_override(pptr, idata, idata->ruid)) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Overriding poly for user %d for dir %s", - idata->uid, pptr->dir); - } else { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Need unmount ns for user %d for dir %s", - idata->ruid, pptr->dir); - need_poly = 1; - break; - } - continue; - } else { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Need poly ns for user %d for dir %s", - idata->uid, pptr->dir); - need_poly = 1; - break; - } - } - - /* - * If polyinstantiation is needed, call the unshare system call to - * disassociate from the parent namespace. - */ - if (need_poly) { - if (unshare(CLONE_NEWNS) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Unable to unshare from parent namespace, %m"); - return PAM_SESSION_ERR; - } - } else { - del_polydir_list(idata->polydirs_ptr); - return PAM_SUCCESS; - } - - /* - * Again cycle through all polyinstantiated directories, this time, - * call ns_setup to setup polyinstantiation for a particular entry. - */ - for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - enum unmnt_op dir_unmnt = unmnt; - if (ns_override(pptr, idata, idata->uid)) { - if (unmnt == NO_UNMNT || ns_override(pptr, idata, idata->ruid)) { - continue; - } else { - dir_unmnt = UNMNT_ONLY; - } - } - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Setting poly ns for user %d for dir %s", - idata->uid, pptr->dir); - - if ((dir_unmnt == UNMNT_REMNT) || (dir_unmnt == UNMNT_ONLY)) { - /* - * Check to see if process current directory is in the - * bind mounted instance_parent directory that we are trying to - * umount - */ - if ((changing_dir = cwd_in(pptr->rdir, idata)) < 0) { - retval = PAM_SESSION_ERR; - goto out; - } else if (changing_dir) { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "changing cwd"); - - /* - * Change current working directory to the parent of - * the mount point, that is parent of the orig - * directory where original contents of the polydir - * are available from - */ - strcpy(poly_parent, pptr->rdir); - fptr = strchr(poly_parent, '/'); - cptr = strrchr(poly_parent, '/'); - if (fptr && cptr && (fptr == cptr)) - strcpy(poly_parent, "/"); - else if (cptr) - *cptr = '\0'; - if (chdir(poly_parent) < 0) { - pam_syslog(idata->pamh, LOG_ERR, - "Can't chdir to %s, %m", poly_parent); - } - } - - if (umount(pptr->rdir) < 0) { - int saved_errno = errno; - pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m", - pptr->rdir); - if (saved_errno != EINVAL) { - retval = PAM_SESSION_ERR; - goto out; - } - } else if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "Umount succeeded %s", - pptr->rdir); - } - - if (dir_unmnt != UNMNT_ONLY) { - retval = ns_setup(pptr, idata); - if (retval == PAM_IGNORE) - retval = PAM_SUCCESS; - if (retval != PAM_SUCCESS) - break; - } - } -out: - if (retval != PAM_SUCCESS) - cleanup_tmpdirs(idata); - else if (pam_set_data(idata->pamh, NAMESPACE_POLYDIR_DATA, idata->polydirs_ptr, - cleanup_data) != PAM_SUCCESS) { - pam_syslog(idata->pamh, LOG_ERR, "Unable to set namespace data"); - cleanup_tmpdirs(idata); - return PAM_SYSTEM_ERR; - } - return retval; -} - - -/* - * Orig namespace. This function is called from when closing a pam - * session. If authorized, it unmounts instance directory. - */ -static int orig_namespace(struct instance_data *idata) -{ - struct polydir_s *pptr; - - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "orig namespace for pid %d", - getpid()); - - /* - * Cycle through all polyinstantiated directories from the namespace - * configuration file to see if polyinstantiation was performed for - * this user for each of the entry. If it was, try and unmount - * appropriate polyinstantiated instance directories. - */ - for (pptr = idata->polydirs_ptr; pptr; pptr = pptr->next) { - if (ns_override(pptr, idata, idata->uid)) - continue; - else { - if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, - "Unmounting instance dir for user %d & dir %s", - idata->uid, pptr->dir); - - if (umount(pptr->dir) < 0) { - pam_syslog(idata->pamh, LOG_ERR, "Unmount of %s failed, %m", - pptr->dir); - return PAM_SESSION_ERR; - } else if (idata->flags & PAMNS_DEBUG) - pam_syslog(idata->pamh, LOG_DEBUG, "Unmount of %s succeeded", - pptr->dir); - } - } - - cleanup_tmpdirs(idata); - return 0; -} - - -#ifdef WITH_SELINUX -/* - * This function checks if the calling program has requested context - * change by calling setexeccon(). If context change is not requested - * then it does not make sense to polyinstantiate based on context. - * The return value from this function is used when selecting the - * polyinstantiation method. If context change is not requested then - * the polyinstantiation method is set to USER, even if the configuration - * file lists the method as "context" or "level". - */ -static int ctxt_based_inst_needed(void) -{ - security_context_t scon = NULL; - int rc = 0; - - rc = getexeccon(&scon); - if (rc < 0 || scon == NULL) - return 0; - else { - freecon(scon); - return 1; - } -} -#endif - - -static int get_user_data(struct instance_data *idata) -{ - int retval; - char *user_name; - struct passwd *pwd; - /* - * Lookup user and fill struct items - */ - retval = pam_get_item(idata->pamh, PAM_USER, (void*) &user_name ); - if ( user_name == NULL || retval != PAM_SUCCESS ) { - pam_syslog(idata->pamh, LOG_ERR, "Error recovering pam user name"); - return PAM_SESSION_ERR; - } - - pwd = pam_modutil_getpwnam(idata->pamh, user_name); - if (!pwd) { - pam_syslog(idata->pamh, LOG_ERR, "user unknown '%s'", user_name); - return PAM_USER_UNKNOWN; - } - - /* - * Add the user info to the instance data so we can refer to them later. - */ - idata->user[0] = 0; - strncat(idata->user, user_name, sizeof(idata->user) - 1); - idata->uid = pwd->pw_uid; - idata->gid = pwd->pw_gid; - - /* Fill in RUSER too */ - retval = pam_get_item(idata->pamh, PAM_RUSER, (void*) &user_name ); - if ( user_name != NULL && retval == PAM_SUCCESS && user_name[0] != '\0' ) { - strncat(idata->ruser, user_name, sizeof(idata->ruser) - 1); - pwd = pam_modutil_getpwnam(idata->pamh, user_name); - } else { - pwd = pam_modutil_getpwuid(idata->pamh, getuid()); - } - if (!pwd) { - pam_syslog(idata->pamh, LOG_ERR, "user unknown '%s'", user_name); - return PAM_USER_UNKNOWN; - } - user_name = pwd->pw_name; - - idata->ruser[0] = 0; - strncat(idata->ruser, user_name, sizeof(idata->ruser) - 1); - idata->ruid = pwd->pw_uid; - - return PAM_SUCCESS; -} - -/* - * Entry point from pam_open_session call. - */ -PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED, - int argc, const char **argv) -{ - int i, retval; - struct instance_data idata; - enum unmnt_op unmnt = NO_UNMNT; - - /* init instance data */ - idata.flags = 0; - idata.polydirs_ptr = NULL; - idata.pamh = pamh; -#ifdef WITH_SELINUX - if (is_selinux_enabled()) - idata.flags |= PAMNS_SELINUX_ENABLED; - if (ctxt_based_inst_needed()) - idata.flags |= PAMNS_CTXT_BASED_INST; -#endif - - /* Parse arguments. */ - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - idata.flags |= PAMNS_DEBUG; - if (strcmp(argv[i], "gen_hash") == 0) - idata.flags |= PAMNS_GEN_HASH; - if (strcmp(argv[i], "ignore_config_error") == 0) - idata.flags |= PAMNS_IGN_CONFIG_ERR; - if (strcmp(argv[i], "ignore_instance_parent_mode") == 0) - idata.flags |= PAMNS_IGN_INST_PARENT_MODE; - if (strcmp(argv[i], "use_current_context") == 0) { - idata.flags |= PAMNS_USE_CURRENT_CONTEXT; - idata.flags |= PAMNS_CTXT_BASED_INST; - } - if (strcmp(argv[i], "use_default_context") == 0) { - idata.flags |= PAMNS_USE_DEFAULT_CONTEXT; - idata.flags |= PAMNS_CTXT_BASED_INST; - } - if (strcmp(argv[i], "unmnt_remnt") == 0) - unmnt = UNMNT_REMNT; - if (strcmp(argv[i], "unmnt_only") == 0) - unmnt = UNMNT_ONLY; - if (strcmp(argv[i], "require_selinux") == 0) { - if (~(idata.flags & PAMNS_SELINUX_ENABLED)) { - pam_syslog(idata.pamh, LOG_ERR, - "selinux_required option given and selinux is disabled"); - return PAM_SESSION_ERR; - } - } - } - if (idata.flags & PAMNS_DEBUG) - pam_syslog(idata.pamh, LOG_DEBUG, "open_session - start"); - - retval = get_user_data(&idata); - if (retval != PAM_SUCCESS) - return retval; - - /* - * Parse namespace configuration file which lists directories to - * polyinstantiate, directory where instance directories are to - * be created and the method used for polyinstantiation. - */ - retval = parse_config_file(&idata); - if (retval != PAM_SUCCESS) { - del_polydir_list(idata.polydirs_ptr); - return PAM_SESSION_ERR; - } - - if (idata.polydirs_ptr) { - retval = setup_namespace(&idata, unmnt); - if (idata.flags & PAMNS_DEBUG) { - if (retval) - pam_syslog(idata.pamh, LOG_DEBUG, - "namespace setup failed for pid %d", getpid()); - else - pam_syslog(idata.pamh, LOG_DEBUG, - "namespace setup ok for pid %d", getpid()); - } - } else if (idata.flags & PAMNS_DEBUG) - pam_syslog(idata.pamh, LOG_DEBUG, "Nothing to polyinstantiate"); - - if (retval != PAM_SUCCESS) - del_polydir_list(idata.polydirs_ptr); - return retval; -} - - -/* - * Entry point from pam_close_session call. - */ -PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags UNUSED, - int argc, const char **argv) -{ - int i, retval; - struct instance_data idata; - void *polyptr; - - /* init instance data */ - idata.flags = 0; - idata.polydirs_ptr = NULL; - idata.pamh = pamh; -#ifdef WITH_SELINUX - if (is_selinux_enabled()) - idata.flags |= PAMNS_SELINUX_ENABLED; - if (ctxt_based_inst_needed()) - idata.flags |= PAMNS_CTXT_BASED_INST; -#endif - - /* Parse arguments. */ - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "debug") == 0) - idata.flags |= PAMNS_DEBUG; - if (strcmp(argv[i], "ignore_config_error") == 0) - idata.flags |= PAMNS_IGN_CONFIG_ERR; - if (strcmp(argv[i], "no_unmount_on_close") == 0) - idata.flags |= PAMNS_NO_UNMOUNT_ON_CLOSE; - } - - if (idata.flags & PAMNS_DEBUG) - pam_syslog(idata.pamh, LOG_DEBUG, "close_session - start"); - - /* - * For certain trusted programs such as newrole, open session - * is called from a child process while the parent perfoms - * close session and pam end functions. For these commands - * pam_close_session should not perform the unmount of the - * polyinstantiatied directory because it will result in - * undoing of parents polyinstantiatiaion. These commands - * will invoke pam_namespace with the "no_unmount_on_close" - * argument. - */ - if (idata.flags & PAMNS_NO_UNMOUNT_ON_CLOSE) { - if (idata.flags & PAMNS_DEBUG) - pam_syslog(idata.pamh, LOG_DEBUG, "close_session - sucessful"); - return PAM_SUCCESS; - } - - retval = get_user_data(&idata); - if (retval != PAM_SUCCESS) - return retval; - - retval = pam_get_data(idata.pamh, NAMESPACE_POLYDIR_DATA, (const void **)&polyptr); - if (retval != PAM_SUCCESS || polyptr == NULL) - /* nothing to reset */ - return PAM_SUCCESS; - - idata.polydirs_ptr = polyptr; - - if (idata.flags & PAMNS_DEBUG) - pam_syslog(idata.pamh, LOG_DEBUG, "Resetting namespace for pid %d", - getpid()); - - retval = orig_namespace(&idata); - if (idata.flags & PAMNS_DEBUG) { - if (retval) - pam_syslog(idata.pamh, LOG_DEBUG, - "resetting namespace failed for pid %d", getpid()); - else - pam_syslog(idata.pamh, LOG_DEBUG, - "resetting namespace ok for pid %d", getpid()); - } - - pam_set_data(idata.pamh, NAMESPACE_POLYDIR_DATA, NULL, NULL); - - return PAM_SUCCESS; -} - -#ifdef PAM_STATIC - -/* static module data */ - -struct pam_module _pam_namespace_modstruct = { - "pam_namespace", - NULL, - NULL, - NULL, - pam_sm_open_session, - pam_sm_close_session, - NULL -}; -#endif diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h deleted file mode 100644 index bfc0da17..00000000 --- a/modules/pam_namespace/pam_namespace.h +++ /dev/null @@ -1,168 +0,0 @@ -/****************************************************************************** - * A module for Linux-PAM that will set the default namespace after - * establishing a session via PAM. - * - * (C) Copyright IBM Corporation 2005 - * (C) Copyright Red Hat 2006 - * All Rights Reserved. - * - * Written by: Janak Desai <janak@us.ibm.com> - * With Revisions by: Steve Grubb <sgrubb@redhat.com> - * Derived from a namespace setup patch by Chad Sellers <cdselle@tycho.nsa.gov> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#if !(defined(linux)) -#error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!! -#endif - -#include "config.h" - -#include <stdio.h> -#include <stdio_ext.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <stdlib.h> -#include <errno.h> -#include <syslog.h> -#include <dlfcn.h> -#include <stdarg.h> -#include <pwd.h> -#include <grp.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/resource.h> -#include <sys/mount.h> -#include <sys/wait.h> -#include <libgen.h> -#include <fcntl.h> -#include <sched.h> -#include <glob.h> -#include <locale.h> -#include "security/pam_modules.h" -#include "security/pam_modutil.h" -#include "security/pam_ext.h" -#include "md5.h" - -#ifdef WITH_SELINUX -#include <selinux/selinux.h> -#include <selinux/get_context_list.h> -#include <selinux/context.h> -#endif - -#ifndef CLONE_NEWNS -#define CLONE_NEWNS 0x00020000 /* Flag to create new namespace */ -#endif - -/* - * Module defines - */ -#ifndef SECURECONF_DIR -#define SECURECONF_DIR "/etc/security/" -#endif - -#define PAM_NAMESPACE_CONFIG (SECURECONF_DIR "namespace.conf") -#define NAMESPACE_INIT_SCRIPT (SECURECONF_DIR "namespace.init") -#define NAMESPACE_D_DIR (SECURECONF_DIR "namespace.d/") -#define NAMESPACE_D_GLOB (SECURECONF_DIR "namespace.d/*.conf") - -/* module flags */ -#define PAMNS_DEBUG 0x00000100 /* Running in debug mode */ -#define PAMNS_SELINUX_ENABLED 0x00000400 /* SELinux is enabled */ -#define PAMNS_CTXT_BASED_INST 0x00000800 /* Context based instance needed */ -#define PAMNS_GEN_HASH 0x00002000 /* Generate md5 hash for inst names */ -#define PAMNS_IGN_CONFIG_ERR 0x00004000 /* Ignore format error in conf file */ -#define PAMNS_IGN_INST_PARENT_MODE 0x00008000 /* Ignore instance parent mode */ -#define PAMNS_NO_UNMOUNT_ON_CLOSE 0x00010000 /* no unmount at session close */ -#define PAMNS_USE_CURRENT_CONTEXT 0x00020000 /* use getcon instead of getexeccon */ -#define PAMNS_USE_DEFAULT_CONTEXT 0x00040000 /* use get_default_context instead of getexeccon */ - -/* polydir flags */ -#define POLYDIR_EXCLUSIVE 0x00000001 /* polyinstatiate exclusively for override uids */ -#define POLYDIR_CREATE 0x00000002 /* create the polydir */ -#define POLYDIR_NOINIT 0x00000004 /* no init script */ -#define POLYDIR_SHARED 0x00000008 /* share context/level instances among users */ -#define POLYDIR_ISCRIPT 0x00000010 /* non default init script */ - - -#define NAMESPACE_MAX_DIR_LEN 80 -#define NAMESPACE_POLYDIR_DATA "pam_namespace:polydir_data" - -/* - * Polyinstantiation method options, based on user, security context - * or both - */ -enum polymethod { - NONE, - USER, - CONTEXT, - LEVEL, - TMPDIR, - TMPFS -}; - -/* - * Depending on the application using this namespace module, we - * may need to unmount priviously bind mounted instance directory. - * Applications such as login and sshd, that establish a new - * session unmount of instance directory is not needed. For applications - * such as su and newrole, that switch the identity, this module - * has to unmount previous instance directory first and re-mount - * based on the new indentity. For other trusted applications that - * just want to undo polyinstantiation, only unmount of previous - * instance directory is needed. - */ -enum unmnt_op { - NO_UNMNT, - UNMNT_REMNT, - UNMNT_ONLY, -}; - -/* - * Structure that holds information about a directory to polyinstantiate - */ -struct polydir_s { - char dir[PATH_MAX]; /* directory to polyinstantiate */ - char rdir[PATH_MAX]; /* directory to unmount (based on RUSER) */ - char instance_prefix[PATH_MAX]; /* prefix for instance dir path name */ - enum polymethod method; /* method used to polyinstantiate */ - unsigned int num_uids; /* number of override uids */ - uid_t *uid; /* list of override uids */ - unsigned int flags; /* polydir flags */ - char *init_script; /* path to init script */ - uid_t owner; /* user which should own the polydir */ - gid_t group; /* group which should own the polydir */ - mode_t mode; /* mode of the polydir */ - struct polydir_s *next; /* pointer to the next polydir entry */ -}; - -struct instance_data { - pam_handle_t *pamh; /* The pam handle for this instance */ - struct polydir_s *polydirs_ptr; /* The linked list pointer */ - char user[LOGIN_NAME_MAX]; /* User name */ - char ruser[LOGIN_NAME_MAX]; /* Requesting user name */ - uid_t uid; /* The uid of the user */ - gid_t gid; /* The gid of the user's primary group */ - uid_t ruid; /* The uid of the requesting user */ - unsigned long flags; /* Flags for debug, selinux etc */ -}; diff --git a/modules/pam_namespace/tst-pam_namespace b/modules/pam_namespace/tst-pam_namespace deleted file mode 100755 index c929dfcf..00000000 --- a/modules/pam_namespace/tst-pam_namespace +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -../../tests/tst-dlopen .libs/pam_namespace.so |