pam_unix.c revision 46665
1/*-
2 * Copyright 1998 Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: head/lib/libpam/modules/pam_unix/pam_unix.c 46665 1999-05-08 01:59:27Z jdp $
27 */
28
29#include <sys/types.h>
30#include <sys/time.h>
31#include <login_cap.h>
32#include <pwd.h>
33#include <stdlib.h>
34#include <string.h>
35#include <stdio.h>
36#include <unistd.h>
37
38#define PAM_SM_AUTH
39#define PAM_SM_ACCOUNT
40#include <security/pam_modules.h>
41
42#include "pam_mod_misc.h"
43
44#define PASSWORD_PROMPT	"Password:"
45
46/*
47 * authentication management
48 */
49
50PAM_EXTERN int
51pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
52    const char **argv)
53{
54	int retval;
55	const char *user;
56	const char *password;
57	struct passwd *pwd;
58	char *encrypted;
59	int options;
60	int i;
61
62	options = 0;
63	for (i = 0;  i < argc;  i++)
64		pam_std_option(&options, argv[i]);
65	if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
66		return retval;
67	if ((retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT,
68	    options)) != PAM_SUCCESS)
69		return retval;
70	if ((pwd = getpwnam(user)) != NULL) {
71		encrypted = crypt(password, pwd->pw_passwd);
72		if (password[0] == '\0' && pwd->pw_passwd[0] != '\0')
73			encrypted = ":";
74
75		retval = strcmp(encrypted, pwd->pw_passwd) == 0 ?
76		    PAM_SUCCESS : PAM_AUTH_ERR;
77	} else {
78		/*
79		 * User unknown.  Encrypt anyway so that it takes the
80		 * same amount of time.
81		 */
82		crypt(password, "xx");
83		retval = PAM_AUTH_ERR;
84	}
85	/*
86	 * The PAM infrastructure will obliterate the cleartext
87	 * password before returning to the application.
88	 */
89	return retval;
90}
91
92PAM_EXTERN int
93pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
94{
95	return PAM_SUCCESS;
96}
97
98/*
99 * account management
100 *
101 * check pw_change and pw_expire fields
102 */
103PAM_EXTERN
104int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
105		     int argc, const char **argv)
106{
107	const char *user;
108	struct passwd *pw;
109	struct timeval tp;
110	time_t warntime;
111	login_cap_t *lc = NULL;
112	char buf[128];
113	int retval;
114
115	retval = pam_get_item(pamh, PAM_USER, (const void **)&user);
116	if (retval != PAM_SUCCESS || user == NULL)
117		/* some implementations return PAM_SUCCESS here */
118		return PAM_USER_UNKNOWN;
119
120	if ((pw = getpwnam(user)) == NULL)
121		return PAM_USER_UNKNOWN;
122
123	retval = PAM_SUCCESS;
124	lc = login_getpwclass(pw);
125
126	if (pw->pw_change || pw->pw_expire)
127		gettimeofday(&tp, NULL);
128
129#define DEFAULT_WARN  (2L * 7L * 86400L)  /* Two weeks */
130
131	warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN,
132	    DEFAULT_WARN);
133
134	if (pw->pw_change) {
135		if (tp.tv_sec >= pw->pw_change)
136			/* some implementations return PAM_AUTHTOK_EXPIRED */
137			retval = PAM_NEW_AUTHTOK_REQD;
138		else if (pw->pw_change - tp.tv_sec < warntime) {
139			snprintf(buf, sizeof(buf),
140			    "Warning: your password expires on %s",
141			    ctime(&pw->pw_change));
142			pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL);
143		}
144	}
145
146	warntime = login_getcaptime(lc, "warnexpire", DEFAULT_WARN,
147	    DEFAULT_WARN);
148
149	if (pw->pw_expire) {
150		if (tp.tv_sec >= pw->pw_expire)
151			retval = PAM_ACCT_EXPIRED;
152		else if (pw->pw_expire - tp.tv_sec < warntime) {
153			snprintf(buf, sizeof(buf),
154			    "Warning: your account expires on %s",
155			    ctime(&pw->pw_expire));
156			pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL);
157		}
158	}
159
160	login_close(lc);
161	return retval;
162}
163
164PAM_MODULE_ENTRY("pam_unix");
165