1115462Sdes/*-
2115462Sdes * Copyright (c) 2003 Networks Associates Technology, Inc.
3115462Sdes * All rights reserved.
4115462Sdes *
5115462Sdes * Portions of this software were developed for the FreeBSD Project by
6115462Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network
7115462Sdes * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
8115462Sdes * ("CBOSS"), as part of the DARPA CHATS research program.
9115462Sdes *
10115462Sdes * Redistribution and use in source and binary forms, with or without
11115462Sdes * modification, are permitted provided that the following conditions
12115462Sdes * are met:
13115462Sdes * 1. Redistributions of source code must retain the above copyright
14115462Sdes *    notice, this list of conditions and the following disclaimer.
15115462Sdes * 2. Redistributions in binary form must reproduce the above copyright
16115462Sdes *    notice, this list of conditions and the following disclaimer in the
17115462Sdes *    documentation and/or other materials provided with the distribution.
18115462Sdes * 3. The name of the author may not be used to endorse or promote
19115462Sdes *    products derived from this software without specific prior written
20115462Sdes *    permission.
21115462Sdes *
22115462Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23115462Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24115462Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25115462Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26115462Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27115462Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28115462Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29115462Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30115462Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31115462Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32115462Sdes * SUCH DAMAGE.
33115462Sdes */
34115462Sdes
35115462Sdes#include <sys/cdefs.h>
36115462Sdes__FBSDID("$FreeBSD$");
37115462Sdes
38115462Sdes#include <string.h>
39115462Sdes
40115462Sdes#define PAM_SM_AUTH
41115462Sdes
42115462Sdes#include <security/pam_appl.h>
43115462Sdes#include <security/pam_modules.h>
44115462Sdes#include <security/openpam.h>
45115462Sdes
46115462Sdes#define DEFAULT_GUESTS	"guest"
47115462Sdes
48115462Sdesstatic int
49115462Sdeslookup(const char *str, const char *list)
50115462Sdes{
51115462Sdes	const char *next;
52115462Sdes	size_t len;
53115462Sdes
54115462Sdes	len = strlen(str);
55115462Sdes	while (*list != '\0') {
56115462Sdes		while (*list == ',')
57115462Sdes			++list;
58115462Sdes		if ((next = strchr(list, ',')) == NULL)
59115462Sdes			next = strchr(list, '\0');
60115462Sdes		if (next - list == (ptrdiff_t)len &&
61115462Sdes		    strncmp(list, str, len) == 0)
62115462Sdes			return (1);
63115462Sdes		list = next;
64115462Sdes	}
65115462Sdes	return (0);
66115462Sdes}
67115462Sdes
68115462SdesPAM_EXTERN int
69115462Sdespam_sm_authenticate(pam_handle_t *pamh, int flags __unused,
70115462Sdes    int argc __unused, const char *argv[] __unused)
71115462Sdes{
72115462Sdes	const char *authtok, *guests, *user;
73115462Sdes	int err, is_guest;
74115462Sdes
75115462Sdes	/* get target account */
76115462Sdes	if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL)
77115462Sdes		return (PAM_AUTH_ERR);
78115462Sdes
79115462Sdes	/* get list of guest logins */
80115462Sdes	if ((guests = openpam_get_option(pamh, "guests")) == NULL)
81115462Sdes		guests = DEFAULT_GUESTS;
82115462Sdes
83115462Sdes	/* check if the target account is on the list */
84115462Sdes	is_guest = lookup(user, guests);
85115462Sdes
86115462Sdes	/* check password */
87115462Sdes	if (!openpam_get_option(pamh, "nopass")) {
88115462Sdes		err = pam_get_authtok(pamh, PAM_AUTHTOK, &authtok, NULL);
89115462Sdes		if (err != PAM_SUCCESS)
90115462Sdes			return (err);
91115462Sdes		if (openpam_get_option(pamh, "pass_is_user") &&
92115462Sdes		    strcmp(user, authtok) != 0)
93115462Sdes			return (PAM_AUTH_ERR);
94115462Sdes		if (openpam_get_option(pamh, "pass_as_ruser"))
95115462Sdes			pam_set_item(pamh, PAM_RUSER, authtok);
96115462Sdes	}
97115462Sdes
98115462Sdes	/* done */
99115462Sdes	if (is_guest) {
100115462Sdes		pam_setenv(pamh, "GUEST", user, 1);
101115462Sdes		return (PAM_SUCCESS);
102115462Sdes	}
103115462Sdes	return (PAM_AUTH_ERR);
104115462Sdes}
105115462Sdes
106115462SdesPAM_EXTERN int
107115462Sdespam_sm_setcred(pam_handle_t * pamh __unused, int flags __unused,
108115462Sdes    int argc __unused, const char *argv[] __unused)
109115462Sdes{
110115462Sdes
111115462Sdes	return (PAM_SUCCESS);
112115462Sdes}
113115462Sdes
114115462SdesPAM_MODULE_ENTRY("pam_guest");
115