diff --git a/options.h b/options.h index 213a7a9..02edbf2 100644 --- a/options.h +++ b/options.h @@ -110,12 +110,18 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ #define MOTD_FILENAME "/etc/motd" #endif -/* Authentication types to enable, at least one required. +/* Authentication Types - at least one required. RFC Draft requires pubkey auth, and recommends password */ + +/* PAM auth is quite simple, and only works for PAM modules which just do a + * simple "Login: " "Password: " (or something like that - if your module is + * similar but not quite like that, edit the strings in svr-authpam.c). + * Basically, it's useful for systems like OS X where standard password crypts + * don't work, but there's and interface via a PAM module. You'll need to + * configure with --enable-pam as well, since it's off by default. And you + * should only enable either PASSWORD _or_ PAM auth, not both. */ + /*#define ENABLE_SVR_PASSWORD_AUTH*/ -/* Only set PAM auth if you aren't using SVR_PASSWORD_AUTH. Also, you'll need - * to make sure PAM libraries etc are installed. To the client, PAM auth looks - * just like password auth. */ #define ENABLE_SVR_PAM_AUTH #define ENABLE_SVR_PUBKEY_AUTH diff --git a/svr-auth.c b/svr-auth.c index 7c4a08c..425f94e 100644 --- a/svr-auth.c +++ b/svr-auth.c @@ -55,7 +55,7 @@ static void authclear() { #ifdef ENABLE_SVR_PUBKEY_AUTH ses.authstate.authtypes |= AUTH_TYPE_PUBKEY; #endif -#if defined(ENABLE_SVR_PUBKEY_AUTH) || defined(ENABLE_SVR_PAM_AUTH) +#if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH) if (!svr_opts.noauthpass) { ses.authstate.authtypes |= AUTH_TYPE_PASSWORD; } diff --git a/svr-authpam.c b/svr-authpam.c index e271020..75192f3 100644 --- a/svr-authpam.c +++ b/svr-authpam.c @@ -1,7 +1,8 @@ /* - * Dropbear - a SSH2 server + * Dropbear SSH * - * Copyright (c) 2002,2003 Matt Johnston + * Copyright (c) 2004 Martin Carlsson + * Portions (c) 2004 Matt Johnston * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,7 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -/* Validates a user password */ +/* Validates a user password using PAM */ #include "includes.h" #include "session.h" @@ -51,9 +52,19 @@ pamConvFunc(int num_msg, int rc = PAM_SUCCESS; struct pam_response* resp = NULL; struct UserDataS* userDatap = (struct UserDataS*) appdata_ptr; + const char* message = (*msg)->msg; TRACE(("enter pamConvFunc")); + + if (num_msg != 1) { + /* If you're getting here - Dropbear probably can't support your pam + * modules. This whole file is a bit of a hack around lack of + * asynchronocity in PAM anyway */ + dropbear_log(LOG_INFO, "pamConvFunc() called with >1 messages: not supported."); + return PAM_CONV_ERR; + } + TRACE(("msg_style is %d", (*msg)->msg_style)); if (message) { TRACE(("message is '%s'", message)); @@ -71,11 +82,14 @@ pamConvFunc(int num_msg, break; } - /* XXX leak */ + /* This looks leaky, but the PAM module-writer docs + * assure us that the caller will free it... */ resp = (struct pam_response*) m_malloc(sizeof(struct pam_response)); - /* XXX leak */ - resp->resp = (char*) m_strdup(userDatap->passwd); - resp->resp_retcode = 0; + memset(resp, 0, sizeof(struct pam_response)); + + /* Safe to just use the direct pointer (no strdup) since + * it shouldn't be getting munged at all */ + resp->resp = userDatap->passwd; (*respp) = resp; break; @@ -90,24 +104,18 @@ pamConvFunc(int num_msg, break; } - /* XXX leak */ + /* This looks leaky, but the PAM module-writer docs + * assure us that the caller will free it... */ resp = (struct pam_response*) m_malloc(sizeof(struct pam_response)); - /* XXX leak */ - resp->resp = (char*) m_strdup(userDatap->user); + memset(resp, 0, sizeof(struct pam_response)); + + /* Safe to just use the direct pointer (no strdup) since + * it shouldn't be getting munged at all */ + resp->resp = userDatap->user; TRACE(("userDatap->user='%s'", userDatap->user)); - - resp->resp_retcode = 0; (*respp) = resp; break; - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - case PAM_RADIO_TYPE: - case PAM_BINARY_PROMPT: - TRACE(("Unhandled message type")); - rc = PAM_CONV_ERR; - break; - default: TRACE(("Unknown message type")); rc = PAM_CONV_ERR; @@ -120,7 +128,9 @@ pamConvFunc(int num_msg, } /* Process a password auth request, sending success or failure messages as - * appropriate. To the client it looks like it's doing normal password auth (as opposed to keyboard-interactive or something), so the pam module has to be fairly standard (ie just "what's your username, what's your password, OK"). + * appropriate. To the client it looks like it's doing normal password auth (as + * opposed to keyboard-interactive or something), so the pam module has to be + * fairly standard (ie just "what's your username, what's your password, OK"). * * Keyboard interactive would be a lot nicer, but since PAM is synchronous, it * gets very messy trying to send the interactive challenges, and read the diff --git a/svr-runopts.c b/svr-runopts.c index dfd5daf..06ffafc 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -59,7 +59,7 @@ static void printhelp(const char * progname) { "-m Don't display the motd on login\n" #endif "-w Disallow root logins\n" -#ifdef ENABLE_SVR_PASSWORD_AUTH +#if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH) "-s Disable password logins\n" "-g Disable password logins for root\n" #endif @@ -183,7 +183,7 @@ void svr_getopts(int argc, char ** argv) { case 'w': svr_opts.norootlogin = 1; break; -#ifdef ENABLE_SVR_PASSWORD_AUTH +#if defined(ENABLE_SVR_PASSWORD_AUTH) || defined(ENABLE_SVR_PAM_AUTH) case 's': svr_opts.noauthpass = 1; break;