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 27 #pragma ident "%Z%%M% %I% %E% SMI" 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 /*ARGSUSED*/ 65 int 66 pam_sm_authenticate( 67 pam_handle_t *pamh, 68 int flags, 69 int argc, 70 const char **argv) 71 { 72 char *user; 73 struct pam_conv *pam_convp; 74 int err, result = PAM_AUTH_ERR; 75 struct pam_response *ret_resp = (struct pam_response *)0; 76 char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; 77 int debug = 0; 78 int try_first_pass = 0; 79 int use_first_pass = 0; 80 int first_pass_good = 0; 81 int first_pass_bad = 0; 82 int i, num_msg; 83 char *firstpass, *password; 84 char the_password[64]; 85 86 if (debug) 87 syslog(LOG_DEBUG, "Sample Authentication\n"); 88 89 (void) strcpy(the_password, "test"); 90 91 for (i = 0; i < argc; i++) { 92 if (strcmp(argv[i], "debug") == 0) 93 debug = 1; 94 else if (strcmp(argv[i], "try_first_pass") == 0) 95 try_first_pass = 1; 96 else if (strcmp(argv[i], "first_pass_good") == 0) 97 first_pass_good = 1; 98 else if (strcmp(argv[i], "first_pass_bad") == 0) 99 first_pass_bad = 1; 100 else if (strcmp(argv[i], "use_first_pass") == 0) 101 use_first_pass = 1; 102 else if (strcmp(argv[i], "always_fail") == 0) 103 return (PAM_AUTH_ERR); 104 else if (strcmp(argv[i], "always_succeed") == 0) 105 return (PAM_SUCCESS); 106 else if (strcmp(argv[i], "always_ignore") == 0) 107 return (PAM_IGNORE); 108 else if (sscanf(argv[i], "pass=%64s", the_password) == 1) { 109 /*EMPTY*/; 110 } 111 else 112 syslog(LOG_DEBUG, "illegal scheme option %s", argv[i]); 113 } 114 115 err = pam_get_user(pamh, &user, NULL); 116 if (err != PAM_SUCCESS) 117 return (err); 118 119 err = pam_get_item(pamh, PAM_CONV, (void**) &pam_convp); 120 if (err != PAM_SUCCESS) 121 return (err); 122 123 (void) pam_get_item(pamh, PAM_AUTHTOK, (void **) &firstpass); 124 125 if (firstpass && (use_first_pass || try_first_pass)) { 126 127 if ((first_pass_good || 128 strncmp(firstpass, the_password, 129 strlen(the_password)) == 0) && 130 !first_pass_bad) { 131 result = PAM_SUCCESS; 132 goto out; 133 } 134 if (use_first_pass) goto out; 135 } 136 137 /* 138 * Get the password from the user 139 */ 140 if (firstpass) { 141 (void) snprintf(messages[0], sizeof (messages[0]), 142 dgettext(TEXT_DOMAIN, "TEST Password: ")); 143 } else { 144 (void) snprintf(messages[0], sizeof (messages[0]), 145 dgettext(TEXT_DOMAIN, "Password: ")); 146 } 147 num_msg = 1; 148 err = __get_authtok(pam_convp->conv, 149 num_msg, messages, NULL, &ret_resp); 150 151 if (err != PAM_SUCCESS) { 152 result = err; 153 goto out; 154 } 155 156 password = ret_resp->resp; 157 158 if (password == NULL) { 159 result = PAM_AUTH_ERR; 160 goto out; 161 } 162 163 /* one last ditch attempt to "login" to TEST */ 164 165 if (strncmp(password, the_password, strlen(the_password)) == 0) { 166 result = PAM_SUCCESS; 167 if (firstpass == NULL) { 168 /* this is the first password, stash it away */ 169 (void) pam_set_item(pamh, PAM_AUTHTOK, password); 170 } 171 } 172 173 out: 174 if (num_msg > 0) { 175 if (ret_resp != 0) { 176 if (ret_resp->resp != 0) { 177 /* avoid leaving password cleartext around */ 178 (void) memset(ret_resp->resp, 0, 179 strlen(ret_resp->resp)); 180 } 181 __free_resp(num_msg, ret_resp); 182 ret_resp = 0; 183 } 184 } 185 186 return (result); 187 } 188