diff -crN openssh-3.6p1/Makefile.in openssh-3.6p1.krb5-kbdintdev/Makefile.in *** openssh-3.6p1/Makefile.in Thu Mar 20 19:51:35 2003 --- openssh-3.6p1.krb5-kbdintdev/Makefile.in Fri Apr 25 14:41:39 2003 *************** *** 81,87 **** monitor_mm.o monitor.o monitor_wrap.o monitor_fdpass.o \ kexdhs.o kexgexs.o \ auth-krb5.o auth-krb4.o \ ! loginrec.o auth-pam.o auth2-pam.o auth-sia.o md5crypt.o MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5 --- 81,87 ---- monitor_mm.o monitor.o monitor_wrap.o monitor_fdpass.o \ kexdhs.o kexgexs.o \ auth-krb5.o auth-krb4.o \ ! loginrec.o auth-pam.o auth2-pam.o auth-sia.o md5crypt.o auth-krb5-kbdint.o MANPAGES = scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out MANPAGES_IN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5 diff -crN openssh-3.6p1/auth-krb5-kbdint.c openssh-3.6p1.krb5-kbdintdev/auth-krb5-kbdint.c *** openssh-3.6p1/auth-krb5-kbdint.c Wed Dec 31 19:00:00 1969 --- openssh-3.6p1.krb5-kbdintdev/auth-krb5-kbdint.c Thu May 1 14:45:11 2003 *************** *** 0 **** --- 1,542 ---- + /* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + #include "includes.h" + RCSID("$OpenBSD: auth-krb5-kbdint.c,v 1.1 2003/04/25 08:00:00 deraadt Exp $"); + + #include "xmalloc.h" + #include "auth.h" + #include "log.h" + #include "uidswap.h" + #include "monitor_wrap.h" + #include "servconf.h" + + #ifdef KRB5_KBDINT + #include + #ifndef HEIMDAL + #define krb5_get_err_text(context,code) error_message(code) + #endif /* !HEIMDAL */ + + /* Some defines for string/array sizes */ + + #define OSSH_KRB5_MAX_MSGS 5 + #define OSSH_KRB5_MSG_SIZE 64 + #define OSSH_KRB5_BANNER_SIZE 1024 + + /* Values for krb5_auth_state */ + + #define OSSH_KRB5_AUTH_INIT 0 + #define OSSH_KRB5_AUTH_BANNER_ONLY 1 + #define OSSH_KRB5_AUTH_BANNER_SENT 2 + + static char global_responses[OSSH_KRB5_MAX_MSGS][OSSH_KRB5_MSG_SIZE]; + static char global_banner[OSSH_KRB5_BANNER_SIZE]; + static char global_password[OSSH_KRB5_MSG_SIZE]; + + static int krb5_auth_state = OSSH_KRB5_AUTH_INIT; + static int prompter_calls = 0; + + int + krb5_verify_pass(Authctxt *authctxt, char *password, krb5_prompter_fct prompter); + + krb5_error_code + krb5_prompter_ossh(krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]); + + /* + * The execution path should look roughly like this: + * + * + * auth2_challenge_start + * krb5_kbdint_init_ctx + * send_userauth_info_request + * krb5_kbdint_query (setup prompts to client) + * (send prompts to client) + * input_userauth_info_response + * (get responses back from client) + * krb5_kbdint_respond + * (copy responses to global data for prompter) + * krb5_verify_pass + * krb5_get_init_creds_password + * krb5_prompter_ossh + * + * Note, we're rolling our own prompts, and ignoring those sent to the + * prompter by krb5_g_i_c_p(). + * + */ + + static void * + krb5_kbdint_init_ctx(Authctxt *authctxt) + { + krb5_error_code problem; + static int cleanup_registered = 0; + + if (authctxt->krb5_ctx == NULL) { + problem = krb5_init_context(&authctxt->krb5_ctx); + if (problem) + goto out; + krb5_init_ets(authctxt->krb5_ctx); + } + if (!cleanup_registered) { + fatal_add_cleanup(krb5_cleanup_proc, authctxt); + cleanup_registered = 1; + } + problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, + &authctxt->krb5_user); + + if (problem) { + debug("problem in krb5_parse_name"); + goto out; + } + out: + if (problem) { + if (authctxt->krb5_ctx != NULL && problem!=-1) + debug("Kerberos password authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos password authentication failed: %d", + problem); + + krb5_cleanup_proc(authctxt); + return NULL; + } + + return authctxt; + + } + + int + krb5_kbdint_query(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on) + { + Authctxt *authctxt = ctx; + char prompt_buf[OSSH_KRB5_MSG_SIZE]; + + /* + * We have to roll our own prompts since we don't call + * krb5_g_i_c_p() until krb5_kbdint_respond() + * + * We decide on how many prompts to send depending on the value of + * krb5_auth_state. Right now, this handles generating prompts + * for initial password and password change. In the event of + * an informational message (banner), no prompts are generated. + * + * Support for other types of conversations could easily be added, + * but I don't know of any for Kerberos at this time. + */ + + switch (krb5_auth_state) { + case OSSH_KRB5_AUTH_INIT: + snprintf(prompt_buf, sizeof(prompt_buf) - 1, "Kerberos password for %s@%s:", + authctxt->krb5_user->data->data, + authctxt->krb5_user->realm.data); + + *name = xstrdup(""); + *infotxt = xstrdup(""); + *numprompts = 1; + *prompts = xmalloc(*numprompts * sizeof(char *)); + *echo_on = xmalloc(*numprompts * sizeof(u_int)); + (*echo_on)[0] = 0; + (*prompts)[0] = xstrdup(prompt_buf); + break; + + case KRB5_CHPW_FAIL: + case KRB5KDC_ERR_KEY_EXP: + *name = xstrdup(""); + *infotxt = xstrdup(global_banner); + *numprompts = 2; + *prompts = xmalloc(*numprompts * sizeof(char *)); + *echo_on = xmalloc(*numprompts * sizeof(u_int)); + (*echo_on)[0] = 0; + (*echo_on)[1] = 0; + (*prompts)[0] = xstrdup("Enter new Kerberos password:"); + (*prompts)[1] = xstrdup("Enter new Kerberos password again:"); + break; + + case OSSH_KRB5_AUTH_BANNER_ONLY: + *name = xstrdup(""); + *infotxt = xstrdup(global_banner); + *numprompts = 0; + *prompts = xmalloc(1); + *echo_on = xmalloc(1); + krb5_auth_state = OSSH_KRB5_AUTH_BANNER_SENT; + break; + + default: + debug("%s: unknown auth state: %d", __func__, krb5_auth_state); + return -1; + } + + return 0; + } + + /* krb5_kbdint_respond + * + * Returns one of the following: + * + * 0 : successful auth + * 1 : need more info, call send_userauth_info_request again + * -1 : error + * + */ + + int + krb5_kbdint_respond(void *ctx, u_int numresponses, char **responses) + { + Authctxt *authctxt = ctx; + int ret, i; + + /* + * Copy responses from client into global_responses[] so the prompter + * will have access to them when called by krb5_g_i_c_p() + */ + + for (i = 0;i < numresponses; i++) { + if (i == OSSH_KRB5_MAX_MSGS) { + debug("%s: more than %d responses", __func__, OSSH_KRB5_MAX_MSGS); + return -1; + } + strlcpy(global_responses[i], responses[i], OSSH_KRB5_MSG_SIZE); + } + + switch(krb5_auth_state) { + case OSSH_KRB5_AUTH_INIT: /* init pass */ + ret = krb5_verify_pass(authctxt, NULL, krb5_prompter_ossh); + break; + + case KRB5KDC_ERR_KEY_EXP: /* pass change, send in orig pass as well */ + ret = krb5_verify_pass(authctxt, global_password, krb5_prompter_ossh); + break; + + case OSSH_KRB5_AUTH_BANNER_SENT: + ret = 0; + break; + + default: + debug("%s: unknown auth state for krb5_auth_state: %d", __func__, + krb5_auth_state); + ret = -1; + } + + if (ret != 1) { /* we're not coming back */ + + /* clear out passwords */ + + memset(global_password, 0, OSSH_KRB5_MSG_SIZE); + for (i = 0; i < OSSH_KRB5_MAX_MSGS; i++) { + memset(global_responses[i], 0, OSSH_KRB5_MSG_SIZE); + } + } + + return ret; + + } + + static void + krb5_kbdint_free_ctx(void *ctx) + { + Authctxt *authctxt = ctx; + + /* + * not sure what to do here -- we don't want to clean up + * authctxt->krb5_ctx until we log out (I don't think). + */ + } + + /* + * krb5_verify_pass: returns one of the following (a la krb5_kbdint_respond() ) + * + * 0 : success + * 1 : need/have more info + * -1 : error + * + * This routine will return 1 (more info) for the following: + * + * - the initial password was successful, but a message + * was returned (banner) + * - a password change is indicated + */ + + /* code taken from auth-krb5.c */ + + int + krb5_verify_pass(Authctxt *authctxt, char *password, krb5_prompter_fct prompter) + { + #ifndef HEIMDAL + krb5_creds creds; + krb5_principal server; + char ccname[40]; + int tmpfd; + #endif + + int problem; + + #ifdef HEIMDAL + problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, + &authctxt->krb5_fwd_ccache); + if (problem) + goto out; + + problem = krb5_cc_initialize(authctxt->krb5_ctx, + authctxt->krb5_fwd_ccache, authctxt->krb5_user); + if (problem) + goto out; + + restore_uid(); + problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, + authctxt->krb5_fwd_ccache, password, 1, NULL); + temporarily_use_uid(authctxt->pw); + + if (problem) + goto out; + + #else + prompter_calls = 0; + problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds, + authctxt->krb5_user, (char *)password, prompter, NULL, 0, NULL, NULL); + if (problem) + goto out; + + problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL, + KRB5_NT_SRV_HST, &server); + if (problem) + goto out; + + restore_uid(); + problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server, + NULL, NULL, NULL); + krb5_free_principal(authctxt->krb5_ctx, server); + temporarily_use_uid(authctxt->pw); + if (problem) + goto out; + + if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, + authctxt->pw->pw_name)) { + problem = -1; + goto out; + } + + snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid()); + + if ((tmpfd = mkstemp(ccname+strlen("FILE:")))==-1) { + log("mkstemp(): %.100s", strerror(errno)); + problem = errno; + goto out; + } + + if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + log("fchmod(): %.100s", strerror(errno)); + close(tmpfd); + problem = errno; + goto out; + } + close(tmpfd); + + problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache); + if (problem) + goto out; + + problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, + authctxt->krb5_user); + if (problem) + goto out; + + problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, + &creds); + if (problem) + goto out; + #endif + + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + + out: + restore_uid(); + + if (problem) { + if (authctxt->krb5_ctx != NULL && problem!=-1) + debug("Kerberos kbdint authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos kbdint authentication failed: %d", + problem); + + if (problem == KRB5KDC_ERR_KEY_EXP) { + krb5_auth_state = problem; + return 1; + } else { + krb5_cleanup_proc(authctxt); + return -1; + } + } + + if (krb5_auth_state == OSSH_KRB5_AUTH_BANNER_ONLY) + return 1; /* one more info req */ + + return (0); + } + + krb5_error_code + krb5_prompter_ossh(krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) + { + int i; + + /* Increment each time the prompter is called, reset in krb5_verify_pass */ + + prompter_calls++; + + /* + * Make sure we don't have more prompts than global responses. + */ + + if (num_prompts >= OSSH_KRB5_MAX_MSGS) { + debug("too many prompts: %d", num_prompts); + return -1; + } + + /* + * Copy values (set in krb5_kbdint_respond) from global_responses into the + * prompts. + */ + + for (i = 0; i < num_prompts; i++) { + strlcpy(prompts[i].reply->data, global_responses[i], OSSH_KRB5_MSG_SIZE); + prompts[i].reply->length = strlen(global_responses[i]); + } + + if (banner) + strlcpy(global_banner, banner, OSSH_KRB5_BANNER_SIZE); + + switch (num_prompts) { + + case 0: /* banner only */ + krb5_auth_state = OSSH_KRB5_AUTH_BANNER_ONLY; + return 0; + + case 1: /* password */ + /* + * Copy the initial password into global_password for use in the + * event of an eventual password change. Note that the password + * is copied into global_responses[0] for a typical login as well. + */ + strlcpy(global_password, global_responses[0], OSSH_KRB5_MSG_SIZE); + return 0; + + case 2: /* pass change */ + + /* + * Gak, if the pass change fails, the prompter is called + * within krb5_g_i_c_p() twice more. For now, if the prompter + * has been called more than once, and the number of prompts + * is 2, figure password change failed, and leave krb5_g_i_c_p(), + * starting over + */ + + if (prompter_calls > 1) + return KRB5KDC_ERR_KEY_EXP; + + switch (krb5_auth_state) { + + /* + * Password change indicated. If this is the first call to + * krb5_g_i_c_p(), return KRB5KDC_ERR_KEY_EXP, which will + * also be the return code for krb5_g_i_c_p() + */ + + case OSSH_KRB5_AUTH_INIT: + return KRB5KDC_ERR_KEY_EXP; + + /* + * Second time through, we've already copied the passwords from + * global_responses[] into the prompt replies, so return 0, allowing + * krb5_g_i_c_p() to do its work changing the pw. + */ + + case KRB5KDC_ERR_KEY_EXP: + return 0; + + default: /* problem */ + debug("%s: unknown auth state: %d", __func__, krb5_auth_state); + return -1; + } + + default: /* problem */ + debug("%s: invalid number of prompts: %d", __func__, num_prompts); + return -1; + } + return -1; + } + + #ifndef KRB5 + void + krb5_cleanup_proc(void *context) + { + Authctxt *authctxt = (Authctxt *)context; + + debug("krb5_cleanup_proc called"); + if (authctxt->krb5_fwd_ccache) { + krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_fwd_ccache = NULL; + } + if (authctxt->krb5_user) { + krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); + authctxt->krb5_user = NULL; + } + if (authctxt->krb5_auth_ctx) { + krb5_auth_con_free(authctxt->krb5_ctx, + authctxt->krb5_auth_ctx); + authctxt->krb5_auth_ctx = NULL; + } + if (authctxt->krb5_ctx) { + krb5_free_context(authctxt->krb5_ctx); + authctxt->krb5_ctx = NULL; + } + } + #endif + + KbdintDevice krb5_kbdint_device = { + "krb5_kbdint", + krb5_kbdint_init_ctx, + krb5_kbdint_query, + krb5_kbdint_respond, + krb5_kbdint_free_ctx + }; + + KbdintDevice mm_krb5_kbdint_device = { + "mm_krb5_kbdint", + mm_krb5_kbdint_init_ctx, + mm_krb5_kbdint_query, + mm_krb5_kbdint_respond, + mm_krb5_kbdint_free_ctx + }; + + + #endif /* KRB5_KBDINT */ diff -crN openssh-3.6p1/auth.h openssh-3.6p1.krb5-kbdintdev/auth.h *** openssh-3.6p1/auth.h Thu Sep 26 23:26:01 2002 --- openssh-3.6p1.krb5-kbdintdev/auth.h Thu May 1 12:55:42 2003 *************** *** 38,44 **** #ifdef BSD_AUTH #include #endif ! #ifdef KRB5 #include #endif --- 38,44 ---- #ifdef BSD_AUTH #include #endif ! #if defined(KRB5) || defined(KRB5_KBDINT) #include #endif *************** *** 63,69 **** #ifdef KRB4 char *krb4_ticket_file; #endif ! #ifdef KRB5 krb5_context krb5_ctx; krb5_auth_context krb5_auth_ctx; krb5_ccache krb5_fwd_ccache; --- 63,69 ---- #ifdef KRB4 char *krb4_ticket_file; #endif ! #if defined(KRB5) || defined(KRB5_KBDINT) krb5_context krb5_ctx; krb5_auth_context krb5_auth_ctx; krb5_ccache krb5_fwd_ccache; *************** *** 125,131 **** #endif /* KRB4 */ ! #ifdef KRB5 int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *); int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt); int auth_krb5_password(Authctxt *authctxt, const char *password); --- 125,131 ---- #endif /* KRB4 */ ! #if defined(KRB5) || defined (KRB5_KBDINT) int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *); int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt); int auth_krb5_password(Authctxt *authctxt, const char *password); diff -crN openssh-3.6p1/auth2-chall.c openssh-3.6p1.krb5-kbdintdev/auth2-chall.c *** openssh-3.6p1/auth2-chall.c Wed Jul 3 20:14:18 2002 --- openssh-3.6p1.krb5-kbdintdev/auth2-chall.c Thu May 1 12:57:01 2003 *************** *** 40,49 **** #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; ! #else #ifdef SKEY extern KbdintDevice skey_device; #endif #endif KbdintDevice *devices[] = { --- 40,53 ---- #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; ! #endif ! #ifdef SKEY extern KbdintDevice skey_device; #endif + + #ifdef KRB5_KBDINT + extern KbdintDevice krb5_kbdint_device; #endif KbdintDevice *devices[] = { *************** *** 53,58 **** --- 57,65 ---- #ifdef SKEY &skey_device, #endif + #ifdef KRB5_KBDINT + &krb5_kbdint_device, + #endif #endif NULL }; *************** *** 320,325 **** --- 327,337 ---- void privsep_challenge_enable(void) { + #ifdef KRB5_KBDINT + extern KbdintDevice mm_krb5_kbdint_device; + devices[0] = &mm_krb5_kbdint_device; + #endif + #ifdef BSD_AUTH extern KbdintDevice mm_bsdauth_device; #endif diff -crN openssh-3.6p1/config.h.in openssh-3.6p1.krb5-kbdintdev/config.h.in *** openssh-3.6p1/config.h.in Wed Mar 26 00:12:36 2003 --- openssh-3.6p1.krb5-kbdintdev/config.h.in Thu May 1 14:24:41 2003 *************** *** 201,206 **** --- 201,209 ---- /* Define if compiler implements __func__ */ #undef HAVE___func__ + /* Define if you want Kerberos 5 Keyboard Interactive support */ + #undef KRB5_KBDINT + /* Define if you want Kerberos 5 support */ #undef KRB5 diff -crN openssh-3.6p1/configure.ac openssh-3.6p1.krb5-kbdintdev/configure.ac *** openssh-3.6p1/configure.ac Thu Mar 20 20:15:18 2003 --- openssh-3.6p1.krb5-kbdintdev/configure.ac Thu May 1 14:29:11 2003 *************** *** 1797,1802 **** --- 1797,1840 ---- fi fi + # Check whether user wants Kerberos 5 Kbdint support + KRB5_KBDINT_MSG="yes" + AC_ARG_WITH(kerberos5-kbdint, + [ --with-kerberos5-kbdint=PATH Enable Kerberos 5 support through Keyboard Interactive], + [ + if test "x$withval" != "xno" ; then + if test "x$withval" = "xyes" ; then + KRB5ROOT="/usr/local" + else + KRB5ROOT=${withval} + fi + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" + LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" + AC_DEFINE(KRB5_KBDINT) + KRB5_KBDINT_MSG="yes" + AC_MSG_CHECKING(whether we are using Heimdal) + AC_TRY_COMPILE([ #include ], + [ char *tmp = heimdal_version; ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(HEIMDAL) + K5LIBS="-lkrb5 -ldes -lcom_err -lasn1 -lroken" + ], + [ AC_MSG_RESULT(no) + K5LIBS="-lkrb5 -lk5crypto -lcom_err" + ] + ) + if test ! -z "$need_dash_r" ; then + LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" + fi + if test ! -z "$blibpath" ; then + blibpath="$blibpath:${KRB5ROOT}/lib" + fi + AC_CHECK_LIB(resolv, dn_expand, , ) + + KRB5_KBDINT=yes + fi + ] + ) # Check whether user wants Kerberos 5 support KRB5_MSG="no" AC_ARG_WITH(kerberos5, *************** *** 2524,2529 **** --- 2562,2568 ---- echo " PAM support: ${PAM_MSG}" echo " KerberosIV support: $KRB4_MSG" echo " KerberosV support: $KRB5_MSG" + echo " KerberosV KBDINT support: $KRB5_KBDINT_MSG" echo " Smartcard support: $SCARD_MSG" echo " AFS support: $AFS_MSG" echo " S/KEY support: $SKEY_MSG" diff -crN openssh-3.6p1/monitor.c openssh-3.6p1.krb5-kbdintdev/monitor.c *** openssh-3.6p1/monitor.c Sun Mar 23 17:12:50 2003 --- openssh-3.6p1.krb5-kbdintdev/monitor.c Thu May 1 12:52:01 2003 *************** *** 126,131 **** --- 126,137 ---- #ifdef KRB5 int mm_answer_krb5(int, Buffer *); #endif + #ifdef KRB5_KBDINT + int mm_answer_krb5_kbdint_init_ctx(int, Buffer *); + int mm_answer_krb5_kbdint_query(int, Buffer *); + int mm_answer_krb5_kbdint_respond(int, Buffer *); + int mm_answer_krb5_kbdint_free_ctx(int, Buffer *); + #endif static Authctxt *authctxt; static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ *************** *** 174,179 **** --- 180,194 ---- #endif {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, + #ifdef KRB5 + {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, + #endif + #ifdef KRB5_KBDINT + {MONITOR_REQ_KRB5_KBDINT_INIT_CTX, MON_ISAUTH, mm_answer_krb5_kbdint_init_ctx}, + {MONITOR_REQ_KRB5_KBDINT_QUERY, MON_ISAUTH, mm_answer_krb5_kbdint_query}, + {MONITOR_REQ_KRB5_KBDINT_RESPOND, MON_ISAUTH, mm_answer_krb5_kbdint_respond}, + {MONITOR_REQ_KRB5_KBDINT_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_krb5_kbdint_free_ctx}, + #endif {0, 0, NULL} }; *************** *** 212,217 **** --- 227,238 ---- #ifdef KRB5 {MONITOR_REQ_KRB5, MON_ONCE|MON_AUTH, mm_answer_krb5}, #endif + #ifdef KRB5_KBDINT + {MONITOR_REQ_KRB5_KBDINT_INIT_CTX, MON_ISAUTH, mm_answer_krb5_kbdint_init_ctx}, + {MONITOR_REQ_KRB5_KBDINT_QUERY, MON_ISAUTH, mm_answer_krb5_kbdint_query}, + {MONITOR_REQ_KRB5_KBDINT_RESPOND, MON_ISAUTH, mm_answer_krb5_kbdint_respond}, + {MONITOR_REQ_KRB5_KBDINT_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_krb5_kbdint_free_ctx}, + #endif {0, 0, NULL} }; *************** *** 1380,1385 **** --- 1401,1503 ---- return success; } + #endif + + #ifdef KRB5_KBDINT + static void *krb5_kbdint_authctxt, *krb5_kbdint_authok; + extern KbdintDevice krb5_kbdint_device; + + int + mm_answer_krb5_kbdint_init_ctx(int socket, Buffer *m) + { + debug3("%s", __func__); + krb5_kbdint_authctxt = (krb5_kbdint_device.init_ctx)(authctxt); + buffer_clear(m); + if (krb5_kbdint_authctxt != NULL) { + monitor_permit(mon_dispatch, MONITOR_REQ_KRB5_KBDINT_FREE_CTX, 1); + buffer_put_int(m, 1); + } else { + buffer_put_int(m, 0); + } + mm_request_send(socket, MONITOR_ANS_KRB5_KBDINT_INIT_CTX, m); + return 0; + } + + int + mm_answer_krb5_kbdint_query(int socket, Buffer *m) + { + char *name, *info, **prompts; + u_int num, *echo_on; + int i, ret; + + ret = (krb5_kbdint_device.query)(krb5_kbdint_authctxt, &name, &info, &num, + &prompts, &echo_on); + + /* pick 5 for now as max # messages */ + if (num > 5 || name == NULL || info == NULL) + ret = -1; + buffer_clear(m); + buffer_put_int(m, ret); + buffer_put_cstring(m, name); + xfree(name); + buffer_put_cstring(m, info); + xfree(info); + buffer_put_int(m, num); + for (i = 0; i < num; i++) { + buffer_put_cstring(m, prompts[i]); + xfree(prompts[i]); + buffer_put_int(m, echo_on[i]); + } + + if (prompts != NULL) + xfree(prompts); + if (echo_on != NULL) + xfree(echo_on); + + mm_request_send(socket, MONITOR_ANS_KRB5_KBDINT_QUERY, m); + return 0; + } + + int + mm_answer_krb5_kbdint_respond(int socket, Buffer *m) + { + char **resp; + u_int num; + int i, ret; + + debug3("%s", __func__); + krb5_kbdint_authok = NULL; + num = buffer_get_int(m); + if (num > 0) { + resp = xmalloc(num * sizeof(char *)); + for (i = 0; i < num; ++i) + resp[i] = buffer_get_string(m, NULL); + ret = (krb5_kbdint_device.respond)(krb5_kbdint_authctxt, num, resp); + for (i = 0; i < num; ++i) + xfree(resp[i]); + xfree(resp); + } else { + ret = (krb5_kbdint_device.respond)(krb5_kbdint_authctxt, num, NULL); + } + buffer_clear(m); + buffer_put_int(m, ret); + mm_request_send(socket, MONITOR_ANS_KRB5_KBDINT_RESPOND, m); + auth_method = "keyboard-interactive/krb5_kbdint"; + if (ret == 0) + krb5_kbdint_authok = krb5_kbdint_authctxt; + return (0); + } + + int + mm_answer_krb5_kbdint_free_ctx(int socket, Buffer *m) + { + debug3("%s", __func__); + (krb5_kbdint_device.free_ctx)(krb5_kbdint_authctxt); + buffer_clear(m); + mm_request_send(socket, MONITOR_ANS_KRB5_KBDINT_FREE_CTX, m); + return (krb5_kbdint_authok == krb5_kbdint_authctxt); + } + #endif int diff -crN openssh-3.6p1/monitor.h openssh-3.6p1.krb5-kbdintdev/monitor.h *** openssh-3.6p1/monitor.h Thu Sep 26 23:26:02 2002 --- openssh-3.6p1.krb5-kbdintdev/monitor.h Thu May 1 12:52:19 2003 *************** *** 52,58 **** MONITOR_REQ_KRB4, MONITOR_ANS_KRB4, MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, MONITOR_REQ_PAM_START, ! MONITOR_REQ_TERM }; struct mm_master; --- 52,64 ---- MONITOR_REQ_KRB4, MONITOR_ANS_KRB4, MONITOR_REQ_KRB5, MONITOR_ANS_KRB5, MONITOR_REQ_PAM_START, ! MONITOR_REQ_TERM, ! MONITOR_REQ_KRB5_KBDINT_START, MONITOR_ANS_KRB5_KBDINT_START, ! MONITOR_REQ_KRB5_KBDINT_INIT_CTX, MONITOR_ANS_KRB5_KBDINT_INIT_CTX, ! MONITOR_REQ_KRB5_KBDINT_QUERY, MONITOR_ANS_KRB5_KBDINT_QUERY, ! MONITOR_REQ_KRB5_KBDINT_RESPOND, MONITOR_ANS_KRB5_KBDINT_RESPOND, ! MONITOR_REQ_KRB5_KBDINT_FREE_CTX, MONITOR_ANS_KRB5_KBDINT_FREE_CTX ! }; struct mm_master; diff -crN openssh-3.6p1/monitor_wrap.c openssh-3.6p1.krb5-kbdintdev/monitor_wrap.c *** openssh-3.6p1/monitor_wrap.c Sun Feb 23 20:03:39 2003 --- openssh-3.6p1.krb5-kbdintdev/monitor_wrap.c Thu May 1 12:50:21 2003 *************** *** 1018,1021 **** --- 1018,1106 ---- buffer_free(&m); return (success); } + #endif + + #ifdef KRB5_KBDINT + void * + mm_krb5_kbdint_init_ctx(Authctxt *authctxt) + { + Buffer m; + int success; + + debug3("%s", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5_KBDINT_INIT_CTX, &m); + debug3("%s: waiting for MONITOR_ANS_KRB5_KBDINT_INIT_CTX", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5_KBDINT_INIT_CTX, &m); + success = buffer_get_int(&m); + if (success == 0) { + debug3("%s: krb5_kbdint_init_ctx failed", __func__); + buffer_free(&m); + return (NULL); + } + buffer_free(&m); + return (authctxt); + } + + int mm_krb5_kbdint_query(void *ctx, char **name, char **info, + u_int *num, char ***prompts, u_int **echo_on) + { + Buffer m; + int i, ret; + + debug3("%s", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5_KBDINT_QUERY, &m); + debug3("%s: waiting for MONITOR_ANS_KRB5_KBDINT_QUERY", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5_KBDINT_QUERY, &m); + ret = buffer_get_int(&m); + debug3("%s: krb5_kbdint_query returned %d", __func__, ret); + + *name = buffer_get_string(&m, NULL); + *info = buffer_get_string(&m, NULL); + *num = buffer_get_int(&m); + + *prompts = xmalloc((*num + 1) * sizeof(char *)); + *echo_on = xmalloc((*num + 1) * sizeof(u_int)); + for (i = 0; i < *num; ++i) { + (*prompts)[i] = buffer_get_string(&m, NULL); + (*echo_on)[i] = buffer_get_int(&m); + } + buffer_free(&m); + return (ret); + } + + int + mm_krb5_kbdint_respond(void *ctx, u_int num, char **resp) + { + Buffer m; + int i, ret; + + debug3("%s", __func__); + buffer_init(&m); + buffer_put_int(&m, num); + for (i = 0; i < num; ++i) + buffer_put_cstring(&m, resp[i]); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5_KBDINT_RESPOND, &m); + debug3("%s: waiting for MONITOR_ANS_KRB5_KBDINT_RESPOND", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5_KBDINT_RESPOND, &m); + ret = buffer_get_int(&m); + debug3("%s: krb5_kbdint_respond returned %d", __func__, ret); + buffer_free(&m); + return (ret); + } + + void + mm_krb5_kbdint_free_ctx(void *ctxtp) + { + Buffer m; + + debug3("%s", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5_KBDINT_FREE_CTX, &m); + debug3("%s: waiting for MONITOR_ANS_KRB5_KBDINT_FREE_CTX", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5_KBDINT_FREE_CTX, &m); + buffer_free(&m); + } + #endif diff -crN openssh-3.6p1/monitor_wrap.h openssh-3.6p1.krb5-kbdintdev/monitor_wrap.h *** openssh-3.6p1/monitor_wrap.h Thu Sep 26 23:26:04 2002 --- openssh-3.6p1.krb5-kbdintdev/monitor_wrap.h Thu May 1 12:50:49 2003 *************** *** 93,98 **** --- 93,105 ---- int mm_auth_krb5(void *authctxt, void *auth, char **client, void *reply); #endif + #ifdef KRB5_KBDINT + void *mm_krb5_kbdint_init_ctx(struct Authctxt *); + int mm_krb5_kbdint_query(void *, char **, char **, u_int *, char ***, u_int **); + int mm_krb5_kbdint_respond(void *, u_int, char **); + void mm_krb5_kbdint_free_ctx(void *); + #endif + /* zlib allocation hooks */ void *mm_zalloc(struct mm_master *, u_int, u_int);