The following patch (relative to -current) makes PAM a proper kbd-interactive citizen. There are a few limitations (grep for todo), but the code seems to work OK for protocols 1 & 2 with and without privsep. Please have a play! auth2-pam.c is based on code from FreeBSD. Index: auth2-chall.c ==================================================================RCS file: /var/cvs/openssh/auth2-chall.c,v retrieving revision 1.17 diff -u -r1.17 auth2-chall.c --- auth2-chall.c 22 Mar 2002 02:30:43 -0000 1.17 +++ auth2-chall.c 24 Apr 2002 01:03:14 -0000 @@ -40,11 +40,17 @@ #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; +extern KbdintDevice mm_bsdauth_device; #else #ifdef SKEY extern KbdintDevice skey_device; +extern KbdintDevice mm_skey_device; #endif #endif +#ifdef USE_PAM +extern KbdintDevice pam_device; +extern KbdintDevice mm_pam_device; +#endif KbdintDevice *devices[] = { #ifdef BSD_AUTH @@ -54,6 +60,23 @@ &skey_device, #endif #endif +#ifdef USE_PAM + &pam_device, +#endif + NULL +}; + +KbdintDevice *mm_devices[] = { +#ifdef BSD_AUTH + &mm_bsdauth_device, +#else +#ifdef SKEY + &mm_skey_device, +#endif +#ifdef USE_PAM + &mm_pam_device, +#endif +#endif NULL }; @@ -314,18 +337,8 @@ void privsep_challenge_enable(void) { -#ifdef BSD_AUTH - extern KbdintDevice mm_bsdauth_device; -#endif -#ifdef SKEY - extern KbdintDevice mm_skey_device; -#endif - /* As long as SSHv1 has devices[0] hard coded this is fine */ -#ifdef BSD_AUTH - devices[0] = &mm_bsdauth_device; -#else -#ifdef SKEY - devices[0] = &mm_skey_device; -#endif -#endif + int i; + + for(i = 0; devices[i] != NULL; i++) + devices[i] = mm_devices[i]; } Index: auth2-pam.c ==================================================================RCS file: /var/cvs/openssh/auth2-pam.c,v retrieving revision 1.12 diff -u -r1.12 auth2-pam.c --- auth2-pam.c 22 Jan 2002 12:43:13 -0000 1.12 +++ auth2-pam.c 24 Apr 2002 01:03:15 -0000 @@ -1,158 +1,344 @@ +/*- + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by ThinkSec AS and + * NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/crypto/openssh/auth2-pam.c,v 1.1 2002/03/21 12:18:27 des Exp $ + */ + #include "includes.h" -RCSID("$Id: auth2-pam.c,v 1.12 2002/01/22 12:43:13 djm Exp $"); #ifdef USE_PAM +RCSID("$FreeBSD: src/crypto/openssh/auth2-pam.c,v 1.1 2002/03/21 12:18:27 des Exp $"); + #include <security/pam_appl.h> -#include "ssh.h" -#include "ssh2.h" #include "auth.h" -#include "auth-pam.h" -#include "packet.h" #include "xmalloc.h" -#include "dispatch.h" #include "log.h" +#include "monitor_wrap.h" -static int do_pam_conversation_kbd_int(int num_msg, - const struct pam_message **msg, struct pam_response **resp, - void *appdata_ptr); -void input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt); - -struct { - int finished, num_received, num_expected; - int *prompts; - struct pam_response *responses; -} context_pam2 = {0, 0, 0, NULL}; - -static struct pam_conv conv2 = { - do_pam_conversation_kbd_int, - NULL, +struct pam_ctxt { + char *pam_user; + pid_t pam_pid; + int pam_sock; + int pam_done; }; -int -auth2_pam(Authctxt *authctxt) -{ - int retval = -1; +static void pam_free_ctx(void *); - if (authctxt->user == NULL) - fatal("auth2_pam: internal error: no user"); +/* + * Send message to parent or child. + */ +static int +pam_send(struct pam_ctxt *ctxt, char *fmt, ...) +{ + va_list ap; + char *mstr, buf[2048]; + size_t len; + int r; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (len == -1 || len > sizeof(buf)) + fatal("pam_send: message too long"); + mstr = xstrdup(buf); + if (ctxt->pam_pid != 0) + debug2("to child: %d bytes", len); + r = send(ctxt->pam_sock, mstr, len + 1, MSG_EOR); + free(mstr); + return (r); +} - conv2.appdata_ptr = authctxt; - do_pam_set_conv(&conv2); +/* + * Peek at first byte of next message. + */ +static int +pam_peek(struct pam_ctxt *ctxt) +{ + char ch; - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, - &input_userauth_info_response_pam); - retval = (do_pam_authenticate(0) == PAM_SUCCESS); - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + if (recv(ctxt->pam_sock, &ch, 1, MSG_PEEK) < 1) + return (-1); + return (ch); +} - return retval; +/* + * Receive a message from parent or child. + */ +static char * +pam_receive(struct pam_ctxt *ctxt) +{ + char *buf; + size_t len; + ssize_t rlen; + + len = 64; + buf = NULL; + do { + len *= 2; + buf = xrealloc(buf, len); + rlen = recv(ctxt->pam_sock, buf, len, MSG_PEEK); + if (rlen < 1) { + xfree(buf); + return (NULL); + } + } while (rlen == len); + if (recv(ctxt->pam_sock, buf, len, 0) != rlen) { + xfree(buf); + return (NULL); + } + if (ctxt->pam_pid != 0) + debug2("from child: %s", buf); + return (buf); } +/* + * Conversation function for child process. + */ static int -do_pam_conversation_kbd_int(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) +pam_child_conv(int n, + const struct pam_message **msg, + struct pam_response **resp, + void *data) { - int i, j, done; - char *text; + struct pam_ctxt *ctxt; + int i; - context_pam2.finished = 0; - context_pam2.num_received = 0; - context_pam2.num_expected = 0; - context_pam2.prompts = xmalloc(sizeof(int) * num_msg); - context_pam2.responses = xmalloc(sizeof(struct pam_response) * num_msg); - memset(context_pam2.responses, 0, sizeof(struct pam_response) * num_msg); - - text = NULL; - for (i = 0, context_pam2.num_expected = 0; i < num_msg; i++) { - int style = PAM_MSG_MEMBER(msg, i, msg_style); - switch (style) { - case PAM_PROMPT_ECHO_ON: + ctxt = data; + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return (PAM_CONV_ERR); + if ((*resp = calloc(n, sizeof **resp)) == NULL) + return (PAM_BUF_ERR); + for (i = 0; i < n; ++i) { + resp[i]->resp_retcode = 0; + resp[i]->resp = NULL; + switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_OFF: - context_pam2.num_expected++; + pam_send(ctxt, "p%s", msg[i]->msg); + resp[i]->resp = pam_receive(ctxt); + break; + case PAM_PROMPT_ECHO_ON: + pam_send(ctxt, "P%s", msg[i]->msg); + resp[i]->resp = pam_receive(ctxt); break; - case PAM_TEXT_INFO: case PAM_ERROR_MSG: - default: - /* Capture all these messages to be sent at once */ - message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); + /*pam_send(ctxt, "e%s", msg[i]->msg);*/ break; + case PAM_TEXT_INFO: + /*pam_send(ctxt, "i%s", msg[i]->msg);*/ + break; + default: + goto fail; } } + return (PAM_SUCCESS); + fail: + while (i) + free(resp[--i]); + /* XXX: bzero responses too */ + free(*resp); + *resp = NULL; + return (PAM_CONV_ERR); +} - if (context_pam2.num_expected == 0) - return PAM_SUCCESS; +/* + * Child process. + */ +static void * +pam_child(struct pam_ctxt *ctxt) +{ + struct pam_conv pam_conv = { pam_child_conv, ctxt }; + pam_handle_t *pamh; + int pam_err; + + pam_err = pam_start("sshd", ctxt->pam_user, &pam_conv, &pamh); + if (pam_err != PAM_SUCCESS) + goto auth_fail; + pam_err = pam_authenticate(pamh, 0); + if (pam_err != PAM_SUCCESS) + goto auth_fail; + pam_send(ctxt, "=OK"); + pam_end(pamh, pam_err); + exit(0); + auth_fail: + pam_send(ctxt, "!%s", pam_strerror(pamh, pam_err)); + pam_end(pamh, pam_err); + exit(0); +} - packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); - packet_put_cstring(""); /* Name */ - packet_put_cstring(""); /* Instructions */ - packet_put_cstring(""); /* Language */ - packet_put_int(context_pam2.num_expected); - - for (i = 0, j = 0; i < num_msg; i++) { - int style = PAM_MSG_MEMBER(msg, i, msg_style); - - /* Skip messages which don't need a reply */ - if (style != PAM_PROMPT_ECHO_ON && style != PAM_PROMPT_ECHO_OFF) - continue; - - context_pam2.prompts[j++] = i; - if (text) { - message_cat(&text, PAM_MSG_MEMBER(msg, i, msg)); - packet_put_cstring(text); - text = NULL; - } else - packet_put_cstring(PAM_MSG_MEMBER(msg, i, msg)); - packet_put_char(style == PAM_PROMPT_ECHO_ON); - } - packet_send(); - packet_write_wait(); - - /* - * Grabbing control of execution and spinning until we get what - * we want is probably rude, but it seems to work properly, and - * the client *should* be in lock-step with us, so the loop should - * only be traversed once. - */ - while(context_pam2.finished == 0) { - done = 1; - dispatch_run(DISPATCH_BLOCK, &done, appdata_ptr); - if(context_pam2.finished == 0) - debug("extra packet during conversation"); - } - - if(context_pam2.num_received == context_pam2.num_expected) { - *resp = context_pam2.responses; - return PAM_SUCCESS; - } else - return PAM_CONV_ERR; -} - -void -input_userauth_info_response_pam(int type, u_int32_t seqnr, void *ctxt) -{ - Authctxt *authctxt = ctxt; - unsigned int nresp = 0, rlen = 0, i = 0; - char *resp; - - if (authctxt == NULL) - fatal("input_userauth_info_response_pam: no authentication context"); - - nresp = packet_get_int(); /* Number of responses. */ - debug("got %d responses", nresp); - - for (i = 0; i < nresp; i++) { - int j = context_pam2.prompts[i]; - - resp = packet_get_string(&rlen); - context_pam2.responses[j].resp_retcode = PAM_SUCCESS; - context_pam2.responses[j].resp = xstrdup(resp); - xfree(resp); - context_pam2.num_received++; +static void * +pam_init_ctx(Authctxt *authctxt) +{ + struct pam_ctxt *ctxt; + int socks[2]; + int i; + + ctxt = xmalloc(sizeof *ctxt); + ctxt->pam_user = xstrdup(authctxt->user); + ctxt->pam_done = 0; + if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, socks) == -1) { + error("%s: failed create sockets: %s", + __func__, strerror(errno)); + xfree(ctxt); + return (NULL); + } + if ((ctxt->pam_pid = fork()) == -1) { + error("%s: failed to fork auth-pam child: %s", + __func__, strerror(errno)); + close(socks[0]); + close(socks[1]); + xfree(ctxt); + return (NULL); + } + if (ctxt->pam_pid == 0) { + /* close everything except our end of the pipe */ + ctxt->pam_sock = socks[1]; + for (i = 0; i < getdtablesize(); ++i) + if (i != ctxt->pam_sock) + close(i); + pam_child(ctxt); + /* not reached */ + exit(1); } + ctxt->pam_sock = socks[0]; + close(socks[1]); + return (ctxt); +} - context_pam2.finished = 1; +int +pam_query(void *ctx, char **name, char **info, + u_int *num, char ***prompts, u_int **echo_on) +{ + struct pam_ctxt *ctxt = ctx; + char *msg; - packet_check_eom(); + if ((msg = pam_receive(ctxt)) == NULL) + return (-1); + *name = xstrdup(""); + *info = xstrdup(""); + *prompts = xmalloc(sizeof(char *)); + *echo_on = xmalloc(sizeof(u_int)); + switch (*msg) { + case 'P': + **echo_on = 1; + case 'p': + *num = 1; + **prompts = xstrdup(msg + 1); + **echo_on = (*msg == 'P'); + break; + case '=': + *num = 0; + **echo_on = 0; + ctxt->pam_done = 1; + break; + case '!': + error("%s", msg + 1); + default: + *num = 0; + **echo_on = 0; + xfree(msg); + ctxt->pam_done = -1; + return (-1); + } + xfree(msg); + return (0); } -#endif +int +pam_respond(void *ctx, u_int num, char **resp) +{ + struct pam_ctxt *ctxt = ctx; + char *msg; + + debug2(__func__); + switch (ctxt->pam_done) { + case 1: + return (0); + case 0: + break; + default: + return (-1); + } + if (num != 1) { + error("expected one response, got %u", num); + return (-1); + } + pam_send(ctxt, "%s", *resp); + switch (pam_peek(ctxt)) { + case 'P': + case 'p': + return (1); + case '=': + msg = pam_receive(ctxt); + xfree(msg); + ctxt->pam_done = 1; + return (0); + default: + msg = pam_receive(ctxt); + if (*msg == '!') + error("%s", msg + 1); + xfree(msg); + ctxt->pam_done = -1; + return (-1); + } +} + +static void +pam_free_ctx(void *ctxtp) +{ + struct pam_ctxt *ctxt = ctxtp; + + close(ctxt->pam_sock); + kill(ctxt->pam_pid, SIGHUP); + /* XXX: wait()? */ + xfree(ctxt->pam_user); + xfree(ctxt); +} + +KbdintDevice pam_device = { + "pam", + pam_init_ctx, + pam_query, + pam_respond, + pam_free_ctx +}; + +KbdintDevice mm_pam_device = { + "pam", + mm_pam_init_ctx, + mm_pam_query, + mm_pam_respond, + mm_pam_free_ctx +}; + +#endif /* USE_PAM */ Index: auth2.c ==================================================================RCS file: /var/cvs/openssh/auth2.c,v retrieving revision 1.100 diff -u -r1.100 auth2.c --- auth2.c 23 Apr 2002 10:28:49 -0000 1.100 +++ auth2.c 24 Apr 2002 01:03:17 -0000 @@ -119,8 +119,6 @@ /* challenge-response is implemented via keyboard interactive */ if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; - if (options.pam_authentication_via_kbd_int) - options.kbd_interactive_authentication = 1; dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); @@ -370,10 +368,6 @@ if (options.challenge_response_authentication) authenticated = auth2_challenge(authctxt, devs); -#ifdef USE_PAM - if (authenticated == 0 && options.pam_authentication_via_kbd_int) - authenticated = auth2_pam(authctxt); -#endif xfree(devs); xfree(lang); #ifdef HAVE_CYGWIN Index: monitor.h ==================================================================RCS file: /var/cvs/openssh/monitor.h,v retrieving revision 1.5 diff -u -r1.5 monitor.h --- monitor.h 23 Apr 2002 10:28:49 -0000 1.5 +++ monitor.h 24 Apr 2002 01:03:17 -0000 @@ -38,6 +38,10 @@ MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND, MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY, MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND, + MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, + MONITOR_REQ_PAMQUERY, MONITOR_ANS_PAMQUERY, + MONITOR_REQ_PAMRESPOND, MONITOR_ANS_PAMRESPOND, + MONITOR_REQ_PAM_FREE_CTX, MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED, MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY, MONITOR_REQ_KEYEXPORT, Index: monitor_wrap.c ==================================================================RCS file: /var/cvs/openssh/monitor_wrap.c,v retrieving revision 1.6 diff -u -r1.6 monitor_wrap.c --- monitor_wrap.c 23 Apr 2002 10:28:49 -0000 1.6 +++ monitor_wrap.c 24 Apr 2002 01:03:18 -0000 @@ -804,6 +804,77 @@ return ((authok == 0) ? -1 : 0); } +void * +mm_pam_init_ctx(struct Authctxt *authctxt) +{ + fatal("Not implemented"); + return (NULL); +} + +int +mm_pam_query(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on) +{ + Buffer m; + int res; + char *challenge; + + debug3("%s: entering", __FUNCTION__); + + buffer_init(&m); + mm_request_send(monitor->m_recvfd, MONITOR_REQ_PAMQUERY, &m); + + mm_request_receive_expect(monitor->m_recvfd, MONITOR_ANS_PAMQUERY, &m); + res = buffer_get_int(&m); + if (res == -1) { + debug3("%s: no challenge", __FUNCTION__); + buffer_free(&m); + return (-1); + } + + /* Get the challenge, and format the response */ + challenge = buffer_get_string(&m, NULL); + buffer_free(&m); + + debug3("%s: received challenge: %s", __FUNCTION__, challenge); + + mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); + + (*prompts)[0] = challenge; + xfree(challenge); + + return (0); +} + +int +mm_pam_respond(void *ctx, u_int numresponses, char **responses) +{ + Buffer m; + int authok; + + debug3("%s: entering", __FUNCTION__); + if (numresponses != 1) + return (-1); + + buffer_init(&m); + buffer_put_cstring(&m, responses[0]); + mm_request_send(monitor->m_recvfd, MONITOR_REQ_PAMRESPOND, &m); + + mm_request_receive_expect(monitor->m_recvfd, + MONITOR_ANS_PAMRESPOND, &m); + + authok = buffer_get_int(&m); + buffer_free(&m); + + return ((authok == 0) ? -1 : 0); +} + +void +mm_pam_free_ctx(void *ctxtp) +{ + fatal("Not implemented"); +} + void mm_ssh1_session_id(u_char session_id[16]) { Index: monitor_wrap.h ==================================================================RCS file: /var/cvs/openssh/monitor_wrap.h,v retrieving revision 1.5 diff -u -r1.5 monitor_wrap.h --- monitor_wrap.h 23 Apr 2002 10:28:49 -0000 1.5 +++ monitor_wrap.h 24 Apr 2002 01:03:18 -0000 @@ -82,6 +82,12 @@ int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_skey_respond(void *, u_int, char **); +/* pam */ +void *mm_pam_init_ctx(struct Authctxt *); +int mm_pam_query(void *, char **, char **, u_int *, char ***, u_int **); +int mm_pam_respond(void *, u_int, char **); +void mm_pam_free_ctx(void *); + /* zlib allocation hooks */ void *mm_zalloc(struct mm_master *, u_int, u_int); Index: servconf.c ==================================================================RCS file: /var/cvs/openssh/servconf.c,v retrieving revision 1.86 diff -u -r1.86 servconf.c --- servconf.c 23 Apr 2002 11:04:52 -0000 1.86 +++ servconf.c 24 Apr 2002 01:03:20 -0000 @@ -55,10 +55,6 @@ { memset(options, 0, sizeof(*options)); - /* Portable-specific options */ - options->pam_authentication_via_kbd_int = -1; - - /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; options->listen_addrs = NULL; @@ -129,11 +125,6 @@ void fill_default_server_options(ServerOptions *options) { - /* Portable-specific options */ - if (options->pam_authentication_via_kbd_int == -1) - options->pam_authentication_via_kbd_int = 0; - - /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_1|SSH_PROTO_2; if (options->num_host_key_files == 0) { @@ -258,9 +249,6 @@ /* Keyword tokens. */ typedef enum { sBadOption, /* == unknown option */ - /* Portable-specific options */ - sPAMAuthenticationViaKbdInt, - /* Standard Options */ sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, @@ -294,9 +282,6 @@ const char *name; ServerOpCodes opcode; } keywords[] = { - /* Portable-specific options */ - { "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt }, - /* Standard Options */ { "port", sPort }, { "hostkey", sHostKeyFile }, { "hostdsakey", sHostKeyFile }, /* alias */ @@ -440,12 +425,6 @@ charptr = NULL; opcode = parse_token(arg, filename, linenum); switch (opcode) { - /* Portable-specific options */ - case sPAMAuthenticationViaKbdInt: - intptr = &options->pam_authentication_via_kbd_int; - goto parse_flag; - - /* Standard Options */ case sBadOption: return -1; case sPort: Index: servconf.h ==================================================================RCS file: /var/cvs/openssh/servconf.h,v retrieving revision 1.48 diff -u -r1.48 servconf.h --- servconf.h 22 Mar 2002 03:11:50 -0000 1.48 +++ servconf.h 24 Apr 2002 01:03:20 -0000 @@ -129,7 +129,6 @@ char *authorized_keys_file; /* File containing public keys */ char *authorized_keys_file2; - int pam_authentication_via_kbd_int; } ServerOptions; void initialize_server_options(ServerOptions *); Index: sshd_config ==================================================================RCS file: /var/cvs/openssh/sshd_config,v retrieving revision 1.46 diff -u -r1.46 sshd_config --- sshd_config 23 Apr 2002 11:04:53 -0000 1.46 +++ sshd_config 24 Apr 2002 01:03:21 -0000 @@ -69,10 +69,6 @@ # Kerberos TGT Passing only works with the AFS kaserver #KerberosTgtPassing no -# Set this to 'yes' to enable PAM keyboard-interactive authentication -# Warning: enabling this may bypass the setting of 'PasswordAuthentication' -#PAMAuthenticationViaKbdInt yes - #X11Forwarding no #X11DisplayOffset 10 #X11UseLocalhost yes