pam_opie.c revision 89618
1/*- 2 * Copyright 2000 James Bloom 3 * All rights reserved. 4 * Based upon code Copyright 1998 Juniper Networks, Inc. 5 * Copyright (c) 2001 Networks Associates Technologies, Inc. 6 * All rights reserved. 7 * Copyright (c) 2002 Networks Associates Technologies, Inc. 8 * All rights reserved. 9 * 10 * Portions of this software were developed for the FreeBSD Project by 11 * ThinkSec AS and NAI Labs, the Security Research Division of Network 12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 13 * ("CBOSS"), as part of the DARPA CHATS research program. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. The name of the author may not be used to endorse or promote 24 * products derived from this software without specific prior written 25 * permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40#include <sys/cdefs.h> 41__FBSDID("$FreeBSD: head/lib/libpam/modules/pam_opie/pam_opie.c 89618 2002-01-21 18:46:25Z des $"); 42 43#include <sys/types.h> 44#include <opie.h> 45#include <pwd.h> 46#include <stdio.h> 47#include <string.h> 48#include <unistd.h> 49 50#define PAM_SM_AUTH 51#define PAM_SM_ACCOUNT 52#define PAM_SM_SESSION 53#define PAM_SM_PASSWORD 54 55#include <security/pam_modules.h> 56#include "pam_mod_misc.h" 57 58enum { 59 PAM_OPT_AUTH_AS_SELF = PAM_OPT_STD_MAX, 60 PAM_OPT_NO_FAKE_PROMPTS 61}; 62 63static struct opttab other_options[] = { 64 { "auth_as_self", PAM_OPT_AUTH_AS_SELF }, 65 { "no_fake_prompts", PAM_OPT_NO_FAKE_PROMPTS }, 66 { NULL, 0 } 67}; 68 69PAM_EXTERN int 70pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) 71{ 72 struct opie opie; 73 struct options options; 74 struct passwd *pwd; 75 int retval, i; 76 char *(promptstr[]) = { "%s\nPassword: ", "%s\nPassword [echo on]: "}; 77 char challenge[OPIE_CHALLENGE_MAX]; 78 char prompt[OPIE_CHALLENGE_MAX+22]; 79 char resp[OPIE_SECRET_MAX]; 80 const char *user; 81 const char *response; 82 83 pam_std_option(&options, other_options, argc, argv); 84 85 PAM_LOG("Options processed"); 86 87 user = NULL; 88 if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL)) { 89 if ((pwd = getpwnam(getlogin())) == NULL) 90 PAM_RETURN(PAM_AUTH_ERR); 91 user = pwd->pw_name; 92 } 93 else { 94 retval = pam_get_user(pamh, (const char **)&user, NULL); 95 if (retval != PAM_SUCCESS) 96 PAM_RETURN(retval); 97 } 98 99 PAM_LOG("Got user: %s", user); 100 101 /* 102 * Don't call the OPIE atexit() handler when our program exits, 103 * since the module has been unloaded and we will SEGV. 104 */ 105 opiedisableaeh(); 106 107 /* 108 * If the no_fake_prompts option was given, and the user 109 * doesn't have an OPIE key, just fail rather than present the 110 * user with a bogus OPIE challenge. 111 */ 112 /* XXX generates a const warning because of incorrect prototype */ 113 if (opiechallenge(&opie, (char *)user, challenge) != 0 && 114 pam_test_option(&options, PAM_OPT_NO_FAKE_PROMPTS, NULL)) 115 PAM_RETURN(PAM_AUTH_ERR); 116 117 /* 118 * It doesn't make sense to use a password that has already been 119 * typed in, since we haven't presented the challenge to the user 120 * yet, so clear the stored password. 121 */ 122 pam_set_item(pamh, PAM_AUTHTOK, NULL); 123 124 for (i = 0; i < 2; i++) { 125 snprintf(prompt, sizeof prompt, promptstr[i], challenge); 126 retval = pam_get_pass(pamh, &response, prompt, &options); 127 if (retval != PAM_SUCCESS) { 128 opieunlock(); 129 PAM_RETURN(retval); 130 } 131 132 PAM_LOG("Completed challenge %d: %s", i, response); 133 134 if (response[0] != '\0') 135 break; 136 137 /* Second time round, echo the password */ 138 pam_set_option(&options, PAM_OPT_ECHO_PASS); 139 } 140 141 /* We have to copy the response, because opieverify mucks with it. */ 142 strlcpy(resp, response, sizeof (resp)); 143 144 /* 145 * Opieverify is supposed to return -1 only if an error occurs. 146 * But it returns -1 even if the response string isn't in the form 147 * it expects. Thus we can't log an error and can only check for 148 * success or lack thereof. 149 */ 150 retval = opieverify(&opie, resp) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR; 151 PAM_RETURN(retval); 152} 153 154PAM_EXTERN int 155pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 156{ 157 struct options options; 158 159 pam_std_option(&options, other_options, argc, argv); 160 161 PAM_LOG("Options processed"); 162 163 PAM_RETURN(PAM_SUCCESS); 164} 165 166PAM_EXTERN int 167pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc ,const char **argv) 168{ 169 struct options options; 170 171 pam_std_option(&options, NULL, argc, argv); 172 173 PAM_LOG("Options processed"); 174 175 PAM_RETURN(PAM_IGNORE); 176} 177 178PAM_EXTERN int 179pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) 180{ 181 struct options options; 182 183 pam_std_option(&options, NULL, argc, argv); 184 185 PAM_LOG("Options processed"); 186 187 PAM_RETURN(PAM_IGNORE); 188} 189 190PAM_EXTERN int 191pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) 192{ 193 struct options options; 194 195 pam_std_option(&options, NULL, argc, argv); 196 197 PAM_LOG("Options processed"); 198 199 PAM_RETURN(PAM_IGNORE); 200} 201 202PAM_EXTERN int 203pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) 204{ 205 struct options options; 206 207 pam_std_option(&options, NULL, argc, argv); 208 209 PAM_LOG("Options processed"); 210 211 PAM_RETURN(PAM_IGNORE); 212} 213 214PAM_MODULE_ENTRY("pam_opie"); 215