pam_opie.c revision 79713
1/*- 2 * Copyright 2000 James Bloom 3 * All rights reserved. 4 * Based upon code Copyright 1998 Juniper Networks, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/lib/libpam/modules/pam_opie/pam_opie.c 79713 2001-07-14 08:38:24Z markm $ 28 */ 29 30#include <sys/types.h> 31#include <opie.h> 32#include <pwd.h> 33#include <stdio.h> 34#include <string.h> 35#include <unistd.h> 36 37#define PAM_SM_AUTH 38#include <security/pam_modules.h> 39#include "pam_mod_misc.h" 40 41enum { PAM_OPT_AUTH_AS_SELF=PAM_OPT_STD_MAX }; 42 43static struct opttab other_options[] = { 44 { "auth_as_self", PAM_OPT_AUTH_AS_SELF }, 45 { NULL, 0 } 46}; 47 48PAM_EXTERN int 49pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) 50{ 51 struct opie opie; 52 struct options options; 53 struct passwd *pwd; 54 int retval, i; 55 char *(promptstr[]) = { "%s\nPassword: ", "%s\nPassword [echo on]: "}; 56 char challenge[OPIE_CHALLENGE_MAX]; 57 char prompt[OPIE_CHALLENGE_MAX+22]; 58 char resp[OPIE_SECRET_MAX]; 59 const char *user; 60 const char *response; 61 62 pam_std_option(&options, other_options, argc, argv); 63 64 PAM_LOG("Options processed"); 65 66 /* 67 * It doesn't make sense to use a password that has already been 68 * typed in, since we haven't presented the challenge to the user 69 * yet. 70 */ 71 if (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL) || 72 pam_test_option(&options, PAM_OPT_TRY_FIRST_PASS, NULL)) 73 PAM_RETURN(PAM_AUTH_ERR); 74 75 user = NULL; 76 if (pam_test_option(&options, PAM_OPT_AUTH_AS_SELF, NULL)) { 77 pwd = getpwnam(getlogin()); 78 user = pwd->pw_name; 79 } 80 else { 81 retval = pam_get_user(pamh, (const char **)&user, NULL); 82 if (retval != PAM_SUCCESS) 83 PAM_RETURN(retval); 84 } 85 86 PAM_LOG("Got user: %s", user); 87 88 /* 89 * Don't call the OPIE atexit() handler when our program exits, 90 * since the module has been unloaded and we will SEGV. 91 */ 92 opiedisableaeh(); 93 94 opiechallenge(&opie, (char *)user, challenge); 95 for (i = 0; i < 2; i++) { 96 snprintf(prompt, sizeof prompt, promptstr[i], challenge); 97 retval = pam_get_pass(pamh, &response, prompt, &options); 98 if (retval != PAM_SUCCESS) { 99 opieunlock(); 100 PAM_RETURN(retval); 101 } 102 103 PAM_LOG("Completed challenge %d: %s", i, response); 104 105 if (response[0] != '\0') 106 break; 107 108 /* Second time round, echo the password */ 109 pam_set_option(&options, PAM_OPT_ECHO_PASS); 110 } 111 112 /* We have to copy the response, because opieverify mucks with it. */ 113 snprintf(resp, sizeof resp, "%s", response); 114 115 /* 116 * Opieverify is supposed to return -1 only if an error occurs. 117 * But it returns -1 even if the response string isn't in the form 118 * it expects. Thus we can't log an error and can only check for 119 * success or lack thereof. 120 */ 121 PAM_RETURN(opieverify(&opie, resp) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR); 122} 123 124PAM_EXTERN int 125pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 126{ 127 return PAM_SUCCESS; 128} 129 130PAM_MODULE_ENTRY("pam_opie"); 131