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]); 654448b21cSMark Murray if (options & PAM_OPT_AUTH_AS_SELF) 664448b21cSMark Murray pwd = getpwuid(getuid()); 674448b21cSMark Murray else { 689a10bb17SJohn Polstra if ((retval = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) 699a10bb17SJohn Polstra return retval; 704448b21cSMark Murray pwd = getpwnam(user); 714448b21cSMark Murray } 729a10bb17SJohn Polstra if ((retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, 739a10bb17SJohn Polstra options)) != PAM_SUCCESS) 749a10bb17SJohn Polstra return retval; 754448b21cSMark Murray if (pwd != NULL) { 769a10bb17SJohn Polstra encrypted = crypt(password, pwd->pw_passwd); 77ce9f8663SJohn Polstra if (password[0] == '\0' && pwd->pw_passwd[0] != '\0') 789a10bb17SJohn Polstra encrypted = ":"; 799a10bb17SJohn Polstra 809a10bb17SJohn Polstra retval = strcmp(encrypted, pwd->pw_passwd) == 0 ? 819a10bb17SJohn Polstra PAM_SUCCESS : PAM_AUTH_ERR; 829a10bb17SJohn Polstra } else { 839a10bb17SJohn Polstra /* 849a10bb17SJohn Polstra * User unknown. Encrypt anyway so that it takes the 859a10bb17SJohn Polstra * same amount of time. 869a10bb17SJohn Polstra */ 879a10bb17SJohn Polstra crypt(password, "xx"); 889a10bb17SJohn Polstra retval = PAM_AUTH_ERR; 899a10bb17SJohn Polstra } 909a10bb17SJohn Polstra /* 919a10bb17SJohn Polstra * The PAM infrastructure will obliterate the cleartext 929a10bb17SJohn Polstra * password before returning to the application. 939a10bb17SJohn Polstra */ 949a10bb17SJohn Polstra return retval; 959a10bb17SJohn Polstra } 969a10bb17SJohn Polstra 979a10bb17SJohn Polstra PAM_EXTERN int 989a10bb17SJohn Polstra pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 999a10bb17SJohn Polstra { 1009a10bb17SJohn Polstra return PAM_SUCCESS; 1019a10bb17SJohn Polstra } 1029294327dSJohn Polstra 103d65b34dbSJohn Polstra /* 104d65b34dbSJohn Polstra * account management 105d65b34dbSJohn Polstra * 106d65b34dbSJohn Polstra * check pw_change and pw_expire fields 107d65b34dbSJohn Polstra */ 108d65b34dbSJohn Polstra PAM_EXTERN 109d65b34dbSJohn Polstra int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, 110d65b34dbSJohn Polstra int argc, const char **argv) 111d65b34dbSJohn Polstra { 112d65b34dbSJohn Polstra const char *user; 113d65b34dbSJohn Polstra struct passwd *pw; 114d65b34dbSJohn Polstra struct timeval tp; 115d65b34dbSJohn Polstra time_t warntime; 116d65b34dbSJohn Polstra login_cap_t *lc = NULL; 117d65b34dbSJohn Polstra char buf[128]; 118d65b34dbSJohn Polstra int retval; 119d65b34dbSJohn Polstra 120d65b34dbSJohn Polstra retval = pam_get_item(pamh, PAM_USER, (const void **)&user); 121d65b34dbSJohn Polstra if (retval != PAM_SUCCESS || user == NULL) 122d65b34dbSJohn Polstra /* some implementations return PAM_SUCCESS here */ 123d65b34dbSJohn Polstra return PAM_USER_UNKNOWN; 124d65b34dbSJohn Polstra 125d65b34dbSJohn Polstra if ((pw = getpwnam(user)) == NULL) 126d65b34dbSJohn Polstra return PAM_USER_UNKNOWN; 127d65b34dbSJohn Polstra 128d65b34dbSJohn Polstra retval = PAM_SUCCESS; 129d65b34dbSJohn Polstra lc = login_getpwclass(pw); 130d65b34dbSJohn Polstra 131d65b34dbSJohn Polstra if (pw->pw_change || pw->pw_expire) 132d65b34dbSJohn Polstra gettimeofday(&tp, NULL); 133d65b34dbSJohn Polstra 134d65b34dbSJohn Polstra #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ 135d65b34dbSJohn Polstra 136d65b34dbSJohn Polstra warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN, 137d65b34dbSJohn Polstra DEFAULT_WARN); 138d65b34dbSJohn Polstra 139d65b34dbSJohn Polstra if (pw->pw_change) { 140d65b34dbSJohn Polstra if (tp.tv_sec >= pw->pw_change) 141d65b34dbSJohn Polstra /* some implementations return PAM_AUTHTOK_EXPIRED */ 142d65b34dbSJohn Polstra retval = PAM_NEW_AUTHTOK_REQD; 143d65b34dbSJohn Polstra else if (pw->pw_change - tp.tv_sec < warntime) { 144d65b34dbSJohn Polstra snprintf(buf, sizeof(buf), 145d65b34dbSJohn Polstra "Warning: your password expires on %s", 146d65b34dbSJohn Polstra ctime(&pw->pw_change)); 147d65b34dbSJohn Polstra pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); 148d65b34dbSJohn Polstra } 149d65b34dbSJohn Polstra } 150d65b34dbSJohn Polstra 151d65b34dbSJohn Polstra warntime = login_getcaptime(lc, "warnexpire", DEFAULT_WARN, 152d65b34dbSJohn Polstra DEFAULT_WARN); 153d65b34dbSJohn Polstra 154d65b34dbSJohn Polstra if (pw->pw_expire) { 155d65b34dbSJohn Polstra if (tp.tv_sec >= pw->pw_expire) 156d65b34dbSJohn Polstra retval = PAM_ACCT_EXPIRED; 157d65b34dbSJohn Polstra else if (pw->pw_expire - tp.tv_sec < warntime) { 158d65b34dbSJohn Polstra snprintf(buf, sizeof(buf), 159d65b34dbSJohn Polstra "Warning: your account expires on %s", 160d65b34dbSJohn Polstra ctime(&pw->pw_expire)); 161d65b34dbSJohn Polstra pam_prompt(pamh, PAM_ERROR_MSG, buf, NULL); 162d65b34dbSJohn Polstra } 163d65b34dbSJohn Polstra } 164d65b34dbSJohn Polstra 165d65b34dbSJohn Polstra login_close(lc); 166d65b34dbSJohn Polstra return retval; 167d65b34dbSJohn Polstra } 168d65b34dbSJohn Polstra 1699294327dSJohn Polstra PAM_MODULE_ENTRY("pam_unix"); 170