19a10bb17SJohn Polstra /*- 29a10bb17SJohn Polstra * Copyright 1998 Juniper Networks, Inc. 39a10bb17SJohn Polstra * All rights reserved. 49a10bb17SJohn Polstra * 59a10bb17SJohn Polstra * Redistribution and use in source and binary forms, with or without 69a10bb17SJohn Polstra * modification, are permitted provided that the following conditions 79a10bb17SJohn Polstra * are met: 89a10bb17SJohn Polstra * 1. Redistributions of source code must retain the above copyright 99a10bb17SJohn Polstra * notice, this list of conditions and the following disclaimer. 109a10bb17SJohn Polstra * 2. Redistributions in binary form must reproduce the above copyright 119a10bb17SJohn Polstra * notice, this list of conditions and the following disclaimer in the 129a10bb17SJohn Polstra * documentation and/or other materials provided with the distribution. 139a10bb17SJohn Polstra * 149a10bb17SJohn Polstra * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 159a10bb17SJohn Polstra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169a10bb17SJohn Polstra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 179a10bb17SJohn Polstra * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 189a10bb17SJohn Polstra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 199a10bb17SJohn Polstra * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 209a10bb17SJohn Polstra * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 219a10bb17SJohn Polstra * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 229a10bb17SJohn Polstra * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 239a10bb17SJohn Polstra * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 249a10bb17SJohn Polstra * SUCH DAMAGE. 259a10bb17SJohn Polstra * 269a10bb17SJohn Polstra * $FreeBSD$ 279a10bb17SJohn Polstra */ 289a10bb17SJohn Polstra 299a10bb17SJohn Polstra #include <sys/types.h> 30d65b34dbSJohn Polstra #include <sys/time.h> 31d65b34dbSJohn Polstra #include <login_cap.h> 329a10bb17SJohn Polstra #include <pwd.h> 339a10bb17SJohn Polstra #include <stdlib.h> 349a10bb17SJohn Polstra #include <string.h> 35d65b34dbSJohn Polstra #include <stdio.h> 369a10bb17SJohn Polstra #include <unistd.h> 379a10bb17SJohn Polstra 389a10bb17SJohn Polstra #define PAM_SM_AUTH 39d65b34dbSJohn Polstra #define PAM_SM_ACCOUNT 409a10bb17SJohn Polstra #include <security/pam_modules.h> 419a10bb17SJohn Polstra 429a10bb17SJohn Polstra #include "pam_mod_misc.h" 439a10bb17SJohn Polstra 449a10bb17SJohn Polstra #define PASSWORD_PROMPT "Password:" 459a10bb17SJohn Polstra 46d65b34dbSJohn Polstra /* 47d65b34dbSJohn Polstra * authentication management 48d65b34dbSJohn Polstra */ 49d65b34dbSJohn Polstra 509a10bb17SJohn Polstra PAM_EXTERN int 519a10bb17SJohn Polstra pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, 529a10bb17SJohn Polstra const char **argv) 539a10bb17SJohn Polstra { 549a10bb17SJohn Polstra int retval; 559a10bb17SJohn Polstra const char *user; 569a10bb17SJohn Polstra const char *password; 579a10bb17SJohn Polstra struct passwd *pwd; 589a10bb17SJohn Polstra char *encrypted; 599a10bb17SJohn Polstra int options; 609a10bb17SJohn Polstra int i; 619a10bb17SJohn Polstra 629a10bb17SJohn Polstra options = 0; 639a10bb17SJohn Polstra for (i = 0; i < argc; i++) 649a10bb17SJohn Polstra pam_std_option(&options, argv[i]); 659a10bb17SJohn Polstra if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) 669a10bb17SJohn Polstra return retval; 679a10bb17SJohn Polstra if ((retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, 689a10bb17SJohn Polstra options)) != PAM_SUCCESS) 699a10bb17SJohn Polstra return retval; 709a10bb17SJohn Polstra if ((pwd = getpwnam(user)) != NULL) { 719a10bb17SJohn Polstra encrypted = crypt(password, pwd->pw_passwd); 72ce9f8663SJohn Polstra if (password[0] == '\0' && pwd->pw_passwd[0] != '\0') 739a10bb17SJohn Polstra encrypted = ":"; 749a10bb17SJohn Polstra 759a10bb17SJohn Polstra retval = strcmp(encrypted, pwd->pw_passwd) == 0 ? 769a10bb17SJohn Polstra PAM_SUCCESS : PAM_AUTH_ERR; 779a10bb17SJohn Polstra } else { 789a10bb17SJohn Polstra /* 799a10bb17SJohn Polstra * User unknown. Encrypt anyway so that it takes the 809a10bb17SJohn Polstra * same amount of time. 819a10bb17SJohn Polstra */ 829a10bb17SJohn Polstra crypt(password, "xx"); 839a10bb17SJohn Polstra retval = PAM_AUTH_ERR; 849a10bb17SJohn Polstra } 859a10bb17SJohn Polstra /* 869a10bb17SJohn Polstra * The PAM infrastructure will obliterate the cleartext 879a10bb17SJohn Polstra * password before returning to the application. 889a10bb17SJohn Polstra */ 899a10bb17SJohn Polstra return retval; 909a10bb17SJohn Polstra } 919a10bb17SJohn Polstra 929a10bb17SJohn Polstra PAM_EXTERN int 939a10bb17SJohn Polstra pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 949a10bb17SJohn Polstra { 959a10bb17SJohn Polstra return PAM_SUCCESS; 969a10bb17SJohn Polstra } 979294327dSJohn Polstra 98d65b34dbSJohn Polstra /* 99d65b34dbSJohn Polstra * account management 100d65b34dbSJohn Polstra * 101d65b34dbSJohn Polstra * check pw_change and pw_expire fields 102d65b34dbSJohn Polstra */ 103d65b34dbSJohn Polstra PAM_EXTERN 104d65b34dbSJohn Polstra int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, 105d65b34dbSJohn Polstra int argc, const char **argv) 106d65b34dbSJohn Polstra { 107d65b34dbSJohn Polstra const char *user; 108d65b34dbSJohn Polstra struct passwd *pw; 109d65b34dbSJohn Polstra struct timeval tp; 110d65b34dbSJohn Polstra time_t warntime; 111d65b34dbSJohn Polstra login_cap_t *lc = NULL; 112d65b34dbSJohn Polstra char buf[128]; 113d65b34dbSJohn Polstra int retval; 114d65b34dbSJohn Polstra 115d65b34dbSJohn Polstra retval = pam_get_item(pamh, PAM_USER, (const void **)&user); 116d65b34dbSJohn Polstra if (retval != PAM_SUCCESS || user == NULL) 117d65b34dbSJohn Polstra /* some implementations return PAM_SUCCESS here */ 118d65b34dbSJohn Polstra return PAM_USER_UNKNOWN; 119d65b34dbSJohn Polstra 120d65b34dbSJohn Polstra if ((pw = getpwnam(user)) == NULL) 121d65b34dbSJohn Polstra return PAM_USER_UNKNOWN; 122d65b34dbSJohn Polstra 123d65b34dbSJohn Polstra retval = PAM_SUCCESS; 124d65b34dbSJohn Polstra lc = login_getpwclass(pw); 125d65b34dbSJohn Polstra 126d65b34dbSJohn Polstra if (pw->pw_change || pw->pw_expire) 127d65b34dbSJohn Polstra gettimeofday(&tp, NULL); 128d65b34dbSJohn Polstra 129d65b34dbSJohn Polstra #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ 130d65b34dbSJohn Polstra 131d65b34dbSJohn Polstra warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN, 132d65b34dbSJohn Polstra DEFAULT_WARN); 133d65b34dbSJohn Polstra 134d65b34dbSJohn Polstra if (pw->pw_change) { 135d65b34dbSJohn Polstra if (tp.tv_sec >= pw->pw_change) 136d65b34dbSJohn Polstra /* some implementations return PAM_AUTHTOK_EXPIRED */ 137d65b34dbSJohn Polstra retval = PAM_NEW_AUTHTOK_REQD; 138d65b34dbSJohn Polstra else if (pw->pw_change - tp.tv_sec < warntime) { 139d65b34dbSJohn Polstra snprintf(buf, sizeof(buf), 140d65b34dbSJohn Polstra "Warning: your password expires on %s", 141d65b34dbSJohn Polstra ctime(&pw->pw_change)); 142d65b34dbSJohn Polstra pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); 143d65b34dbSJohn Polstra } 144d65b34dbSJohn Polstra } 145d65b34dbSJohn Polstra 146d65b34dbSJohn Polstra warntime = login_getcaptime(lc, "warnexpire", DEFAULT_WARN, 147d65b34dbSJohn Polstra DEFAULT_WARN); 148d65b34dbSJohn Polstra 149d65b34dbSJohn Polstra if (pw->pw_expire) { 150d65b34dbSJohn Polstra if (tp.tv_sec >= pw->pw_expire) 151d65b34dbSJohn Polstra retval = PAM_ACCT_EXPIRED; 152d65b34dbSJohn Polstra else if (pw->pw_expire - tp.tv_sec < warntime) { 153d65b34dbSJohn Polstra snprintf(buf, sizeof(buf), 154d65b34dbSJohn Polstra "Warning: your account expires on %s", 155d65b34dbSJohn Polstra ctime(&pw->pw_expire)); 156d65b34dbSJohn Polstra pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); 157d65b34dbSJohn Polstra } 158d65b34dbSJohn Polstra } 159d65b34dbSJohn Polstra 160d65b34dbSJohn Polstra login_close(lc); 161d65b34dbSJohn Polstra return retval; 162d65b34dbSJohn Polstra } 163d65b34dbSJohn Polstra 1649294327dSJohn Polstra PAM_MODULE_ENTRY("pam_unix"); 165