From 3ab496b3dd961423bc5e312fd5dbbef975f4d238 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Wed, 14 May 2003 13:47:37 +1000 Subject: [PATCH] - markus@cvs.openbsd.org 2003/05/14 02:15:47 [auth2.c monitor.c sshconnect2.c auth2-krb5.c] implement kerberos over ssh2 ("kerberos-2@ssh.com"); tested with jakob@ server interops with commercial client; ok jakob@ djm@ --- ChangeLog | 6 ++- auth2-krb5.c | 66 +++++++++++++++++++++++++++++++++ auth2.c | 8 +++- monitor.c | 7 +++- sshconnect2.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 auth2-krb5.c diff --git a/ChangeLog b/ChangeLog index 53d039fc3..e37d26ad7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -63,6 +63,10 @@ [sftp.1] emphasise the batchmode functionality and make reference to pubkey auth, both of which are FAQs; ok markus@ + - markus@cvs.openbsd.org 2003/05/14 02:15:47 + [auth2.c monitor.c sshconnect2.c auth2-krb5.c] + implement kerberos over ssh2 ("kerberos-2@ssh.com"); tested with jakob@ + server interops with commercial client; ok jakob@ djm@ 20030512 - (djm) Redhat spec: Don't install profile.d scripts when not @@ -1450,4 +1454,4 @@ save auth method before monitor_reset_key_state(); bugzilla bug #284; ok provos@ -$Id: ChangeLog,v 1.2691 2003/05/14 03:47:07 djm Exp $ +$Id: ChangeLog,v 1.2692 2003/05/14 03:47:37 djm Exp $ diff --git a/auth2-krb5.c b/auth2-krb5.c new file mode 100644 index 000000000..ea4d76da0 --- /dev/null +++ b/auth2-krb5.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 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: auth2-krb5.c,v 1.1 2003/05/14 02:15:47 markus Exp $"); + +#include + +#include "ssh2.h" +#include "xmalloc.h" +#include "packet.h" +#include "log.h" +#include "auth.h" +#include "monitor_wrap.h" +#include "servconf.h" + +/* import */ +extern ServerOptions options; + +static int +userauth_kerberos(Authctxt *authctxt) +{ + krb5_data tkt, reply; + char *client = NULL; + int authenticated = 0; + + tkt.data = packet_get_string(&tkt.length); + packet_check_eom(); + + if (PRIVSEP(auth_krb5(authctxt, &tkt, &client, &reply))) { + authenticated = 1; + if (reply.length) + xfree(reply.data); + } + if (client) + xfree(client); + xfree(tkt.data); + return (authenticated); +} + +Authmethod method_kerberos = { + "kerberos-2@ssh.com", + userauth_kerberos, + &options.kerberos_authentication +}; diff --git a/auth2.c b/auth2.c index b2f14bacd..03d170e23 100644 --- a/auth2.c +++ b/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.97 2003/04/08 20:21:28 itojun Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.98 2003/05/14 02:15:47 markus Exp $"); #include "ssh2.h" #include "xmalloc.h" @@ -50,6 +50,9 @@ extern Authmethod method_pubkey; extern Authmethod method_passwd; extern Authmethod method_kbdint; extern Authmethod method_hostbased; +#ifdef KRB5 +extern Authmethod method_kerberos; +#endif Authmethod *authmethods[] = { &method_none, @@ -57,6 +60,9 @@ Authmethod *authmethods[] = { &method_passwd, &method_kbdint, &method_hostbased, +#ifdef KRB5 + &method_kerberos, +#endif NULL }; diff --git a/monitor.c b/monitor.c index 1f6677581..78d1e2e0c 100644 --- a/monitor.c +++ b/monitor.c @@ -25,7 +25,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: monitor.c,v 1.38 2003/04/08 20:21:28 itojun Exp $"); +RCSID("$OpenBSD: monitor.c,v 1.39 2003/05/14 02:15:47 markus Exp $"); #include @@ -182,6 +182,9 @@ struct mon_table mon_dispatch_proto20[] = { #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 {0, 0, NULL} }; @@ -1483,6 +1486,8 @@ mm_answer_krb5(int socket, Buffer *m) } mm_request_send(socket, MONITOR_ANS_KRB5, m); + auth_method = "kerberos"; + return success; } #endif diff --git a/sshconnect2.c b/sshconnect2.c index 74d699ff2..0605e4e5f 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -23,7 +23,11 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.117 2003/05/12 16:55:37 markus Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.118 2003/05/14 02:15:47 markus Exp $"); + +#ifdef KRB5 +#include +#endif #include "ssh.h" #include "ssh2.h" @@ -190,6 +194,7 @@ int userauth_pubkey(Authctxt *); int userauth_passwd(Authctxt *); int userauth_kbdint(Authctxt *); int userauth_hostbased(Authctxt *); +int userauth_kerberos(Authctxt *); void userauth(Authctxt *, char *); @@ -208,6 +213,12 @@ Authmethod authmethods[] = { userauth_hostbased, &options.hostbased_authentication, NULL}, +#if KRB5 + {"kerberos-2@ssh.com", + userauth_kerberos, + &options.kerberos_authentication, + NULL}, +#endif {"publickey", userauth_pubkey, &options.pubkey_authentication, @@ -1112,6 +1123,94 @@ userauth_hostbased(Authctxt *authctxt) return 1; } +#if KRB5 +static int +ssh_krb5_helper(krb5_data *ap) +{ + krb5_context xcontext = NULL; /* XXX share with ssh1 */ + krb5_auth_context xauth_context = NULL; + + krb5_context *context; + krb5_auth_context *auth_context; + krb5_error_code problem; + const char *tkfile; + struct stat buf; + krb5_ccache ccache = NULL; + const char *remotehost; + int ret; + + memset(ap, 0, sizeof(*ap)); + + context = &xcontext; + auth_context = &xauth_context; + + problem = krb5_init_context(context); + if (problem) { + debug("Kerberos v5: krb5_init_context failed"); + ret = 0; + goto out; + } + + tkfile = krb5_cc_default_name(*context); + if (strncmp(tkfile, "FILE:", 5) == 0) + tkfile += 5; + + if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { + debug("Kerberos v5: could not get default ccache (permission denied)."); + ret = 0; + goto out; + } + + problem = krb5_cc_default(*context, &ccache); + if (problem) { + debug("Kerberos v5: krb5_cc_default failed: %s", + krb5_get_err_text(*context, problem)); + ret = 0; + goto out; + } + + remotehost = get_canonical_hostname(1); + + problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, + "host", remotehost, NULL, ccache, ap); + if (problem) { + debug("Kerberos v5: krb5_mk_req failed: %s", + krb5_get_err_text(*context, problem)); + ret = 0; + goto out; + } + ret = 1; + + out: + if (ccache != NULL) + krb5_cc_close(*context, ccache); + if (*auth_context) + krb5_auth_con_free(*context, *auth_context); + if (*context) + krb5_free_context(*context); + return (ret); +} + +int +userauth_kerberos(Authctxt *authctxt) +{ + krb5_data ap; + + if (ssh_krb5_helper(&ap) == 0) + return (0); + + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_put_string(ap.data, ap.length); + packet_send(); + + krb5_data_free(&ap); + return (1); +} +#endif + /* find auth method */ /*