1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Copyright 2023 OmniOS Community Edition (OmniOSce) Association. 27 */ 28 29 #include <security/pam_appl.h> 30 #include <security/pam_modules.h> 31 #include <string.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <sys/types.h> 35 #include <pwd.h> 36 #include <syslog.h> 37 #include <libintl.h> 38 39 #include "sample_utils.h" 40 41 /* 42 * 43 * Sample module for pam_sm_authenticate. 44 * 45 * options - 46 * 47 * debug 48 * use_first_pass 49 * try_first_pass 50 * first_pass_good (first password is always good when used with use/try) 51 * first_pass_bad (first password is always bad when used with use/try) 52 * pass=foobar (set good password to "foobar". default good password 53 * is test) 54 * always_fail always return PAM_AUTH_ERR 55 * always_succeed always return PAM_SUCCESS 56 * always_ignore 57 * 58 * 59 */ 60 61 /* 62 * pam_sm_authenticate - Authenticate user 63 */ 64 int 65 pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) 66 { 67 const char *user; 68 const struct pam_conv *pam_convp; 69 int err, result = PAM_AUTH_ERR; 70 struct pam_response *ret_resp = (struct pam_response *)0; 71 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; 72 int debug = 0; 73 int try_first_pass = 0; 74 int use_first_pass = 0; 75 int first_pass_good = 0; 76 int first_pass_bad = 0; 77 int i, num_msg; 78 const char *firstpass; 79 char *password; 80 char the_password[64]; 81 82 if (debug) 83 syslog(LOG_DEBUG, "Sample Authentication\n"); 84 85 (void) strcpy(the_password, "test"); 86 87 for (i = 0; i < argc; i++) { 88 if (strcmp(argv[i], "debug") == 0) 89 debug = 1; 90 else if (strcmp(argv[i], "try_first_pass") == 0) 91 try_first_pass = 1; 92 else if (strcmp(argv[i], "first_pass_good") == 0) 93 first_pass_good = 1; 94 else if (strcmp(argv[i], "first_pass_bad") == 0) 95 first_pass_bad = 1; 96 else if (strcmp(argv[i], "use_first_pass") == 0) 97 use_first_pass = 1; 98 else if (strcmp(argv[i], "always_fail") == 0) 99 return (PAM_AUTH_ERR); 100 else if (strcmp(argv[i], "always_succeed") == 0) 101 return (PAM_SUCCESS); 102 else if (strcmp(argv[i], "always_ignore") == 0) 103 return (PAM_IGNORE); 104 else if (sscanf(argv[i], "pass=%64s", the_password) == 1) { 105 /*EMPTY*/; 106 } 107 else 108 syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]); 109 } 110 111 err = pam_get_user(pamh, &user, NULL); 112 if (err != PAM_SUCCESS) 113 return (err); 114 115 err = pam_get_item(pamh, PAM_CONV, (const void**)&pam_convp); 116 if (err != PAM_SUCCESS) 117 return (err); 118 119 (void) pam_get_item(pamh, PAM_AUTHTOK, (const void **)&firstpass); 120 121 if (firstpass && (use_first_pass || try_first_pass)) { 122 123 if ((first_pass_good || 124 strncmp(firstpass, the_password, 125 strlen(the_password)) == 0) && 126 !first_pass_bad) { 127 result = PAM_SUCCESS; 128 goto out; 129 } 130 if (use_first_pass) goto out; 131 } 132 133 /* 134 * Get the password from the user 135 */ 136 if (firstpass) { 137 (void) snprintf(messages[0], sizeof (messages[0]), 138 dgettext(TEXT_DOMAIN, "TEST Password: ")); 139 } else { 140 (void) snprintf(messages[0], sizeof (messages[0]), 141 dgettext(TEXT_DOMAIN, "Password: ")); 142 } 143 num_msg = 1; 144 err = __get_authtok(pam_convp->conv, 145 num_msg, messages, NULL, &ret_resp); 146 147 if (err != PAM_SUCCESS) { 148 result = err; 149 goto out; 150 } 151 152 password = ret_resp->resp; 153 154 if (password == NULL) { 155 result = PAM_AUTH_ERR; 156 goto out; 157 } 158 159 /* one last ditch attempt to "login" to TEST */ 160 161 if (strncmp(password, the_password, strlen(the_password)) == 0) { 162 result = PAM_SUCCESS; 163 if (firstpass == NULL) { 164 /* this is the first password, stash it away */ 165 (void) pam_set_item(pamh, PAM_AUTHTOK, password); 166 } 167 } 168 169 out: 170 if (num_msg > 0) { 171 if (ret_resp != 0) { 172 if (ret_resp->resp != 0) { 173 /* avoid leaving password cleartext around */ 174 (void) memset(ret_resp->resp, 0, 175 strlen(ret_resp->resp)); 176 } 177 __free_resp(num_msg, ret_resp); 178 ret_resp = 0; 179 } 180 } 181 182 return (result); 183 } 184