aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_namespace
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pam_namespace')
-rw-r--r--modules/pam_namespace/.cvsignore9
-rw-r--r--modules/pam_namespace/Makefile.am42
-rw-r--r--modules/pam_namespace/README.xml44
-rw-r--r--modules/pam_namespace/argv_parse.c165
-rw-r--r--modules/pam_namespace/argv_parse.h43
-rw-r--r--modules/pam_namespace/md5.c260
-rw-r--r--modules/pam_namespace/md5.h28
-rw-r--r--modules/pam_namespace/namespace.conf28
-rw-r--r--modules/pam_namespace/namespace.conf.5.xml210
-rwxr-xr-xmodules/pam_namespace/namespace.init24
-rw-r--r--modules/pam_namespace/pam_namespace.8.xml390
-rw-r--r--modules/pam_namespace/pam_namespace.c1907
-rw-r--r--modules/pam_namespace/pam_namespace.h168
-rwxr-xr-xmodules/pam_namespace/tst-pam_namespace2
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 &lt;polydir&gt;. 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 &lt;polydir&gt; to provide an
- instance of &lt;polydir&gt; based on the &lt;method&gt; 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 &lt;user name&gt; for "user"
- method and &lt;user name&gt;_&lt;raw directory context&gt; 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 &lt;service&gt;s you need polyinstantiation (login for example)
- put the following line in /etc/pam.d/&lt;service&gt; 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 &lt;janak@us.ibm.com&gt;.
- More features added by Tomas Mraz &lt;tmraz@redhat.com&gt;.
- </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 &lt;service&gt;s you need polyinstantiation (login for example)
- put the following line in /etc/pam.d/&lt;service&gt; 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 &lt;janak@us.ibm.com&gt;,
- Chad Sellers &lt;csellers@tresys.com&gt; and Steve Grubb &lt;sgrubb@redhat.com&gt;.
- Additional improvements by Xavier Toth &lt;txtoth@gmail.com&gt; and Tomas Mraz
- &lt;tmraz@redhat.com&gt;.
- </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