1*1b695acdSchristos /* $NetBSD: pam_chroot.c,v 1.5 2012/01/03 19:02:54 christos Exp $ */
2e7d22a2eSchristos
36f11bdf1Schristos /*-
46f11bdf1Schristos * Copyright (c) 2003 Networks Associates Technology, Inc.
56f11bdf1Schristos * All rights reserved.
66f11bdf1Schristos *
76f11bdf1Schristos * This software was developed for the FreeBSD Project by ThinkSec AS and
86f11bdf1Schristos * NAI Labs, the Security Research Division of Network Associates, Inc.
96f11bdf1Schristos * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
106f11bdf1Schristos * DARPA CHATS research program.
116f11bdf1Schristos *
126f11bdf1Schristos * Redistribution and use in source and binary forms, with or without
136f11bdf1Schristos * modification, are permitted provided that the following conditions
146f11bdf1Schristos * are met:
156f11bdf1Schristos * 1. Redistributions of source code must retain the above copyright
166f11bdf1Schristos * notice, this list of conditions and the following disclaimer.
176f11bdf1Schristos * 2. Redistributions in binary form must reproduce the above copyright
186f11bdf1Schristos * notice, this list of conditions and the following disclaimer in the
196f11bdf1Schristos * documentation and/or other materials provided with the distribution.
206f11bdf1Schristos * 3. The name of the author may not be used to endorse or promote
216f11bdf1Schristos * products derived from this software without specific prior written
226f11bdf1Schristos * permission.
236f11bdf1Schristos *
246f11bdf1Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
256f11bdf1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
266f11bdf1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
276f11bdf1Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
286f11bdf1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
296f11bdf1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
306f11bdf1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
316f11bdf1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
326f11bdf1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
336f11bdf1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
346f11bdf1Schristos * SUCH DAMAGE.
356f11bdf1Schristos */
366f11bdf1Schristos
376f11bdf1Schristos #include <sys/cdefs.h>
38e7d22a2eSchristos #ifdef __FreeBSD__
396f11bdf1Schristos __FBSDID("$FreeBSD: src/lib/libpam/modules/pam_chroot/pam_chroot.c,v 1.3 2003/04/30 00:40:24 des Exp $");
40e7d22a2eSchristos #else
41*1b695acdSchristos __RCSID("$NetBSD: pam_chroot.c,v 1.5 2012/01/03 19:02:54 christos Exp $");
42e7d22a2eSchristos #endif
436f11bdf1Schristos
446f11bdf1Schristos #include <sys/param.h>
456f11bdf1Schristos
466f11bdf1Schristos #include <pwd.h>
476f11bdf1Schristos #include <stdio.h>
486f11bdf1Schristos #include <string.h>
49*1b695acdSchristos #include <errno.h>
506f11bdf1Schristos #include <unistd.h>
516f11bdf1Schristos
526f11bdf1Schristos #define PAM_SM_SESSION
536f11bdf1Schristos
546f11bdf1Schristos #include <security/pam_appl.h>
556f11bdf1Schristos #include <security/pam_modules.h>
566f11bdf1Schristos #include <security/openpam.h>
576f11bdf1Schristos
586f11bdf1Schristos PAM_EXTERN int
pam_sm_open_session(pam_handle_t * pamh,int flags __unused,int argc __unused,const char * argv[]__unused)596f11bdf1Schristos pam_sm_open_session(pam_handle_t *pamh, int flags __unused,
606f11bdf1Schristos int argc __unused, const char *argv[] __unused)
616f11bdf1Schristos {
626f11bdf1Schristos const char *dir, *end, *cwd, *user;
6359cbc9e2Sthorpej struct passwd *pwd, pwres;
646f11bdf1Schristos char buf[PATH_MAX];
6559cbc9e2Sthorpej char pwbuf[1024];
666f11bdf1Schristos
676f11bdf1Schristos if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS ||
6859cbc9e2Sthorpej user == NULL ||
692a62e4e1Schristos getpwnam_r(user, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
702a62e4e1Schristos pwd == NULL)
716f11bdf1Schristos return (PAM_SESSION_ERR);
726f11bdf1Schristos if (pwd->pw_uid == 0 && !openpam_get_option(pamh, "also_root"))
736f11bdf1Schristos return (PAM_SUCCESS);
746f11bdf1Schristos if (pwd->pw_dir == NULL)
756f11bdf1Schristos return (PAM_SESSION_ERR);
766f11bdf1Schristos if ((end = strstr(pwd->pw_dir, "/./")) != NULL) {
776f11bdf1Schristos if (snprintf(buf, sizeof(buf), "%.*s",
786f11bdf1Schristos (int)(end - pwd->pw_dir), pwd->pw_dir) > (int)sizeof(buf)) {
796f11bdf1Schristos openpam_log(PAM_LOG_ERROR,
806f11bdf1Schristos "%s's home directory is too long", user);
816f11bdf1Schristos return (PAM_SESSION_ERR);
826f11bdf1Schristos }
836f11bdf1Schristos dir = buf;
846f11bdf1Schristos cwd = end + 2;
856f11bdf1Schristos } else if ((dir = openpam_get_option(pamh, "dir")) != NULL) {
866f11bdf1Schristos if ((cwd = openpam_get_option(pamh, "cwd")) == NULL)
876f11bdf1Schristos cwd = "/";
886f11bdf1Schristos } else {
896f11bdf1Schristos if (openpam_get_option(pamh, "always")) {
906f11bdf1Schristos openpam_log(PAM_LOG_ERROR,
916f11bdf1Schristos "%s has no chroot directory", user);
926f11bdf1Schristos return (PAM_SESSION_ERR);
936f11bdf1Schristos }
946f11bdf1Schristos return (PAM_SUCCESS);
956f11bdf1Schristos }
966f11bdf1Schristos
976f11bdf1Schristos openpam_log(PAM_LOG_DEBUG, "chrooting %s to %s", dir, user);
986f11bdf1Schristos
996f11bdf1Schristos if (chroot(dir) == -1) {
100*1b695acdSchristos openpam_log(PAM_LOG_ERROR, "chroot(): %s", strerror(errno));
1016f11bdf1Schristos return (PAM_SESSION_ERR);
1026f11bdf1Schristos }
1036f11bdf1Schristos if (chdir(cwd) == -1) {
104*1b695acdSchristos openpam_log(PAM_LOG_ERROR, "chdir(): %s", strerror(errno));
1056f11bdf1Schristos return (PAM_SESSION_ERR);
1066f11bdf1Schristos }
1076f11bdf1Schristos pam_setenv(pamh, "HOME", cwd, 1);
1086f11bdf1Schristos return (PAM_SUCCESS);
1096f11bdf1Schristos }
1106f11bdf1Schristos
1116f11bdf1Schristos PAM_EXTERN int
pam_sm_close_session(pam_handle_t * pamh __unused,int flags __unused,int argc __unused,const char * argv[]__unused)1126f11bdf1Schristos pam_sm_close_session(pam_handle_t *pamh __unused, int flags __unused,
1136f11bdf1Schristos int argc __unused, const char *argv[] __unused)
1146f11bdf1Schristos {
1156f11bdf1Schristos
1166f11bdf1Schristos return (PAM_SUCCESS);
1176f11bdf1Schristos }
1186f11bdf1Schristos
1196f11bdf1Schristos PAM_MODULE_ENTRY("pam_chroot");
120