199158Sdes/*-
2115619Sdes * Copyright (c) 2002-2003 Networks Associates Technology, Inc.
3348980Sdes * Copyright (c) 2004-2015 Dag-Erling Sm��rgrav
499158Sdes * All rights reserved.
599158Sdes *
699158Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and
799158Sdes * Network Associates Laboratories, the Security Research Division of
899158Sdes * Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
999158Sdes * ("CBOSS"), as part of the DARPA CHATS research program.
1099158Sdes *
1199158Sdes * Redistribution and use in source and binary forms, with or without
1299158Sdes * modification, are permitted provided that the following conditions
1399158Sdes * are met:
1499158Sdes * 1. Redistributions of source code must retain the above copyright
1599158Sdes *    notice, this list of conditions and the following disclaimer.
1699158Sdes * 2. Redistributions in binary form must reproduce the above copyright
1799158Sdes *    notice, this list of conditions and the following disclaimer in the
1899158Sdes *    documentation and/or other materials provided with the distribution.
1999158Sdes * 3. The name of the author may not be used to endorse or promote
2099158Sdes *    products derived from this software without specific prior written
2199158Sdes *    permission.
2299158Sdes *
2399158Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2499158Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2599158Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2699158Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2799158Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2899158Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2999158Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3099158Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3199158Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3299158Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3399158Sdes * SUCH DAMAGE.
3499158Sdes *
35348980Sdes * $OpenPAM: pam_unix.c 938 2017-04-30 21:34:42Z des $
3699158Sdes */
3799158Sdes
38117610Sdes#ifdef HAVE_CONFIG_H
39228692Sdes# include "config.h"
40117610Sdes#endif
41117610Sdes
4299158Sdes#include <sys/param.h>
4399158Sdes
4499158Sdes#include <pwd.h>
4599158Sdes#include <stdlib.h>
4699158Sdes#include <stdio.h>
4799158Sdes#include <string.h>
4899158Sdes#include <unistd.h>
4999158Sdes
50117610Sdes#ifdef HAVE_CRYPT_H
51117610Sdes# include <crypt.h>
52115619Sdes#endif
53115619Sdes
5499158Sdes#include <security/pam_modules.h>
55107937Sdes#include <security/pam_appl.h>
5699158Sdes
57174832Sdes#ifndef OPENPAM
5899158Sdesstatic char password_prompt[] = "Password:";
5999158Sdes#endif
6099158Sdes
6199158Sdes#ifndef PAM_EXTERN
6299158Sdes#define PAM_EXTERN
6399158Sdes#endif
6499158Sdes
6599158SdesPAM_EXTERN int
6699158Sdespam_sm_authenticate(pam_handle_t *pamh, int flags,
6799158Sdes	int argc, const char *argv[])
6899158Sdes{
69174832Sdes#ifndef OPENPAM
7099158Sdes	struct pam_conv *conv;
7199158Sdes	struct pam_message msg;
7299158Sdes	const struct pam_message *msgp;
7399158Sdes	struct pam_response *resp;
7499158Sdes#endif
7599158Sdes	struct passwd *pwd;
7699158Sdes	const char *user;
77280031Sdim	const char *crypt_password, *password;
7899158Sdes	int pam_err, retry;
7999158Sdes
80174832Sdes	(void)argc;
81174832Sdes	(void)argv;
82174832Sdes
8399158Sdes	/* identify user */
8499158Sdes	if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
8599158Sdes		return (pam_err);
8699158Sdes	if ((pwd = getpwnam(user)) == NULL)
8799158Sdes		return (PAM_USER_UNKNOWN);
8899158Sdes
8999158Sdes	/* get password */
90174832Sdes#ifndef OPENPAM
9199158Sdes	pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
9299158Sdes	if (pam_err != PAM_SUCCESS)
9399158Sdes		return (PAM_SYSTEM_ERR);
9499158Sdes	msg.msg_style = PAM_PROMPT_ECHO_OFF;
9599158Sdes	msg.msg = password_prompt;
9699158Sdes	msgp = &msg;
9799158Sdes#endif
9899158Sdes	for (retry = 0; retry < 3; ++retry) {
99174832Sdes#ifdef OPENPAM
10099158Sdes		pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
101280031Sdim		    &password, NULL);
10299158Sdes#else
10399158Sdes		resp = NULL;
10499158Sdes		pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
10599158Sdes		if (resp != NULL) {
10699158Sdes			if (pam_err == PAM_SUCCESS)
10799158Sdes				password = resp->resp;
10899158Sdes			else
10999158Sdes				free(resp->resp);
11099158Sdes			free(resp);
11199158Sdes		}
11299158Sdes#endif
11399158Sdes		if (pam_err == PAM_SUCCESS)
11499158Sdes			break;
11599158Sdes	}
11699158Sdes	if (pam_err == PAM_CONV_ERR)
11799158Sdes		return (pam_err);
11899158Sdes	if (pam_err != PAM_SUCCESS)
11999158Sdes		return (PAM_AUTH_ERR);
12099158Sdes
12199158Sdes	/* compare passwords */
12299158Sdes	if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) ||
12399158Sdes	    (crypt_password = crypt(password, pwd->pw_passwd)) == NULL ||
12499158Sdes	    strcmp(crypt_password, pwd->pw_passwd) != 0)
12599158Sdes		pam_err = PAM_AUTH_ERR;
12699158Sdes	else
12799158Sdes		pam_err = PAM_SUCCESS;
128174832Sdes#ifndef OPENPAM
12999158Sdes	free(password);
13099158Sdes#endif
13199158Sdes	return (pam_err);
13299158Sdes}
13399158Sdes
13499158SdesPAM_EXTERN int
13599158Sdespam_sm_setcred(pam_handle_t *pamh, int flags,
13699158Sdes	int argc, const char *argv[])
13799158Sdes{
13899158Sdes
139174832Sdes	(void)pamh;
140174832Sdes	(void)flags;
141174832Sdes	(void)argc;
142174832Sdes	(void)argv;
14399158Sdes	return (PAM_SUCCESS);
14499158Sdes}
14599158Sdes
14699158SdesPAM_EXTERN int
14799158Sdespam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
14899158Sdes	int argc, const char *argv[])
14999158Sdes{
15099158Sdes
151174832Sdes	(void)pamh;
152174832Sdes	(void)flags;
153174832Sdes	(void)argc;
154174832Sdes	(void)argv;
15599158Sdes	return (PAM_SUCCESS);
15699158Sdes}
15799158Sdes
15899158SdesPAM_EXTERN int
15999158Sdespam_sm_open_session(pam_handle_t *pamh, int flags,
16099158Sdes	int argc, const char *argv[])
16199158Sdes{
16299158Sdes
163174832Sdes	(void)pamh;
164174832Sdes	(void)flags;
165174832Sdes	(void)argc;
166174832Sdes	(void)argv;
16799158Sdes	return (PAM_SUCCESS);
16899158Sdes}
16999158Sdes
17099158SdesPAM_EXTERN int
17199158Sdespam_sm_close_session(pam_handle_t *pamh, int flags,
17299158Sdes	int argc, const char *argv[])
17399158Sdes{
17499158Sdes
175174832Sdes	(void)pamh;
176174832Sdes	(void)flags;
177174832Sdes	(void)argc;
178174832Sdes	(void)argv;
17999158Sdes	return (PAM_SUCCESS);
18099158Sdes}
18199158Sdes
18299158SdesPAM_EXTERN int
18399158Sdespam_sm_chauthtok(pam_handle_t *pamh, int flags,
18499158Sdes	int argc, const char *argv[])
18599158Sdes{
18699158Sdes
187174832Sdes	(void)pamh;
188174832Sdes	(void)flags;
189174832Sdes	(void)argc;
190174832Sdes	(void)argv;
19199158Sdes	return (PAM_SERVICE_ERR);
19299158Sdes}
19399158Sdes
19499158Sdes#ifdef PAM_MODULE_ENTRY
19599158SdesPAM_MODULE_ENTRY("pam_unix");
19699158Sdes#endif
197