1 |
/* $MidnightBSD$ */ |
2 |
/*- |
3 |
* Copyright (c) 2003 Networks Associates Technology, Inc. |
4 |
* All rights reserved. |
5 |
* |
6 |
* This software was developed for the FreeBSD Project by ThinkSec AS and |
7 |
* NAI Labs, the Security Research Division of Network Associates, Inc. |
8 |
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the |
9 |
* DARPA CHATS research program. |
10 |
* |
11 |
* Redistribution and use in source and binary forms, with or without |
12 |
* modification, are permitted provided that the following conditions |
13 |
* are met: |
14 |
* 1. Redistributions of source code must retain the above copyright |
15 |
* notice, this list of conditions and the following disclaimer. |
16 |
* 2. Redistributions in binary form must reproduce the above copyright |
17 |
* notice, this list of conditions and the following disclaimer in the |
18 |
* documentation and/or other materials provided with the distribution. |
19 |
* 3. The name of the author may not be used to endorse or promote |
20 |
* products derived from this software without specific prior written |
21 |
* permission. |
22 |
* |
23 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
24 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
27 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 |
* SUCH DAMAGE. |
34 |
*/ |
35 |
|
36 |
#include <sys/cdefs.h> |
37 |
__FBSDID("$FreeBSD: stable/10/lib/libpam/modules/pam_chroot/pam_chroot.c 114262 2003-04-30 00:40:24Z des $"); |
38 |
|
39 |
#include <sys/param.h> |
40 |
|
41 |
#include <pwd.h> |
42 |
#include <stdio.h> |
43 |
#include <string.h> |
44 |
#include <unistd.h> |
45 |
|
46 |
#define PAM_SM_SESSION |
47 |
|
48 |
#include <security/pam_appl.h> |
49 |
#include <security/pam_modules.h> |
50 |
#include <security/openpam.h> |
51 |
|
52 |
PAM_EXTERN int |
53 |
pam_sm_open_session(pam_handle_t *pamh, int flags __unused, |
54 |
int argc __unused, const char *argv[] __unused) |
55 |
{ |
56 |
const char *dir, *end, *cwd, *user; |
57 |
struct passwd *pwd; |
58 |
char buf[PATH_MAX]; |
59 |
|
60 |
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || |
61 |
user == NULL || (pwd = getpwnam(user)) == NULL) |
62 |
return (PAM_SESSION_ERR); |
63 |
if (pwd->pw_uid == 0 && !openpam_get_option(pamh, "also_root")) |
64 |
return (PAM_SUCCESS); |
65 |
if (pwd->pw_dir == NULL) |
66 |
return (PAM_SESSION_ERR); |
67 |
if ((end = strstr(pwd->pw_dir, "/./")) != NULL) { |
68 |
if (snprintf(buf, sizeof(buf), "%.*s", |
69 |
(int)(end - pwd->pw_dir), pwd->pw_dir) > (int)sizeof(buf)) { |
70 |
openpam_log(PAM_LOG_ERROR, |
71 |
"%s's home directory is too long", user); |
72 |
return (PAM_SESSION_ERR); |
73 |
} |
74 |
dir = buf; |
75 |
cwd = end + 2; |
76 |
} else if ((dir = openpam_get_option(pamh, "dir")) != NULL) { |
77 |
if ((cwd = openpam_get_option(pamh, "cwd")) == NULL) |
78 |
cwd = "/"; |
79 |
} else { |
80 |
if (openpam_get_option(pamh, "always")) { |
81 |
openpam_log(PAM_LOG_ERROR, |
82 |
"%s has no chroot directory", user); |
83 |
return (PAM_SESSION_ERR); |
84 |
} |
85 |
return (PAM_SUCCESS); |
86 |
} |
87 |
|
88 |
openpam_log(PAM_LOG_DEBUG, "chrooting %s to %s", dir, user); |
89 |
|
90 |
if (chroot(dir) == -1) { |
91 |
openpam_log(PAM_LOG_ERROR, "chroot(): %m"); |
92 |
return (PAM_SESSION_ERR); |
93 |
} |
94 |
if (chdir(cwd) == -1) { |
95 |
openpam_log(PAM_LOG_ERROR, "chdir(): %m"); |
96 |
return (PAM_SESSION_ERR); |
97 |
} |
98 |
pam_setenv(pamh, "HOME", cwd, 1); |
99 |
return (PAM_SUCCESS); |
100 |
} |
101 |
|
102 |
PAM_EXTERN int |
103 |
pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused, |
104 |
int argc __unused, const char *argv[] __unused) |
105 |
{ |
106 |
|
107 |
return (PAM_SUCCESS); |
108 |
} |
109 |
|
110 |
PAM_MODULE_ENTRY("pam_chroot"); |