]> andersk Git - gssapi-openssh.git/commitdiff
11 Apr 2003 patch from Simon
authorjbasney <jbasney>
Mon, 14 Apr 2003 14:21:36 +0000 (14:21 +0000)
committerjbasney <jbasney>
Mon, 14 Apr 2003 14:21:36 +0000 (14:21 +0000)
27 files changed:
openssh/Makefile.in
openssh/acconfig.h
openssh/auth-pam.c
openssh/auth-pam.h
openssh/auth.c
openssh/auth.h
openssh/auth2.c
openssh/compat.c
openssh/compat.h
openssh/configure.ac
openssh/kex.c
openssh/kex.h
openssh/key.c
openssh/key.h
openssh/monitor.c
openssh/monitor.h
openssh/monitor_wrap.c
openssh/monitor_wrap.h
openssh/readconf.c
openssh/readconf.h
openssh/servconf.c
openssh/servconf.h
openssh/session.c
openssh/session.h
openssh/sshconnect2.c
openssh/sshd.c
openssh/sshd_config.5

index 583d49140aa07c7fe624235ab01b1c2271efaa10..b24f017addd165ff6f98ab5c23ee4e6af1ada2b8 100644 (file)
@@ -67,7 +67,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \
        key.o dispatch.o kex.o mac.o uuencode.o misc.o \
        rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o kexgex.o \
        kexdhc.o kexgexc.o scard.o msg.o progressmeter.o \
-       entropy.o
+       entropy.o kexgssc.o gss-genr.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
        sshconnect.o sshconnect1.o sshconnect2.o
@@ -79,8 +79,9 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
        auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
        auth2-none.o auth2-passwd.o auth2-pubkey.o \
        monitor_mm.o monitor.o monitor_wrap.o monitor_fdpass.o \
-       kexdhs.o kexgexs.o \
-       auth-krb5.o auth-krb4.o \
+       kexdhs.o kexgexs.o kexgsss.o \
+       auth-krb5.o auth-krb4.o auth2-gss.o \
+       gss-serv.o gss-serv-krb5.o gss-serv-gsi.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
index 3b919d553ea67e1292492fea708d0b809cf953e4..76ba0240a9b3cf99134162c453cef7adebb9a3ae 100644 (file)
 /* Define if compiler implements __func__ */
 #undef HAVE___func__
 
+/* Define this is you want GSSAPI support in the version 2 protocol */
+#undef GSSAPI
+
 /* Define if you want Kerberos 5 support */
 #undef KRB5
 
 /* Define if you want AFS support */
 #undef AFS
 
+/* Define if you want GSI/Globus authentication support */
+#undef GSI
+
 /* Define if you want S/Key support */
 #undef SKEY
 
index c91de9da479923da29fe11f9cb501b2538148449..a8ba48652905daee42e9ffc5d807cd3dfb850dd4 100644 (file)
@@ -423,6 +423,26 @@ void free_pam_environment(char **env)
        }
 }
 
+/* Set a PAM environment string. We need to do this so that the session
+ * modules can handle things like Kerberos/GSI credentials that appear
+ * during the ssh authentication process.
+ */
+
+int do_pam_putenv(char *name, char *value) {
+       char *compound;
+       int ret=1;
+
+#ifdef HAVE_PAM_PUTENV 
+       compound=xmalloc(strlen(name)+strlen(value)+2);
+       if (compound) {
+               sprintf(compound,"%s=%s",name,value);
+               ret=pam_putenv(__pamh,compound);
+               xfree(compound);
+       }
+#endif
+       return(ret);
+}
+
 /* Print any messages that have been generated during authentication */
 /* or account checking to stderr */
 void print_pam_messages(void)
index 585ceb8df2ab17a365a35c7c45b187ae52ea3016..50bf8f3e21500ce4cf666a42ec929ae268332e00 100644 (file)
@@ -44,6 +44,7 @@ void print_pam_messages(void);
 int is_pam_password_change_required(void);
 void do_pam_chauthtok(void);
 void do_pam_set_conv(struct pam_conv *);
+int do_pam_putenv(char *, char *);
 void message_cat(char **p, const char *a);
 
 #endif /* USE_PAM */
index 1268accb1ba1bb08c578b64218be00c476de21b0..ccedf9dcb0f6163a803373a4b8e369760745e94d 100644 (file)
@@ -263,7 +263,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
            authmsg,
            method,
            authctxt->valid ? "" : "illegal user ",
-           authctxt->user,
+           (authctxt->user[0]) ? authctxt->user : "<implicit>",
            get_remote_ipaddr(),
            get_remote_port(),
            info);
index c75d75366bca2ff823691d572b28d5fa4bafc04d..8e63132c92df6307a1f0f062237ea17b6278a600 100644 (file)
@@ -70,6 +70,7 @@ struct Authctxt {
        krb5_principal   krb5_user;
        char            *krb5_ticket_file;
 #endif
+       void *methoddata;
 };
 
 struct Authmethod {
index 1b21eb2dab7b25cf493996f09bdb4873a6c992bf..922073cf803e0c926ad47ea43bcf29499310c6e5 100644 (file)
@@ -36,6 +36,10 @@ RCSID("$OpenBSD: auth2.c,v 1.96 2003/02/06 21:22:43 markus Exp $");
 #include "pathnames.h"
 #include "monitor_wrap.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import */
 extern ServerOptions options;
 extern u_char *session_id2;
@@ -50,9 +54,15 @@ extern Authmethod method_pubkey;
 extern Authmethod method_passwd;
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
+extern Authmethod method_external;
+extern Authmethod method_gssapi;
 
 Authmethod *authmethods[] = {
        &method_none,
+#ifdef GSSAPI
+       &method_external,
+       &method_gssapi,
+#endif
        &method_pubkey,
        &method_passwd,
        &method_kbdint,
@@ -180,6 +190,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        }
        /* reset state */
        auth2_challenge_stop(authctxt);
+
+#ifdef GSSAPI
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+#endif
+
        authctxt->postponed = 0;
 
        /* try to authenticate user */
index 5e1774ab63d5fa1eb50740a5c9217d0dab36a208..bd37d4c51df88ee8880423b10894c2e21f94ea0b 100644 (file)
@@ -71,15 +71,21 @@ compat_datafellows(const char *version)
                { "OpenSSH_2.5.0p1*,"
                  "OpenSSH_2.5.1p1*",
                                        SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
-                                       SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
+                                       SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
+                                       SSH_OLD_GSSAPI},
                { "OpenSSH_2.5.0*,"
                  "OpenSSH_2.5.1*,"
                  "OpenSSH_2.5.2*",     SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
                                        SSH_BUG_EXTEOF},
                { "OpenSSH_2.5.3*",     SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
+               { "OpenSSH_2.9p*",      SSH_BUG_EXTEOF|SSH_OLD_GSSAPI},
                { "OpenSSH_2.*,"
                  "OpenSSH_3.0*,"
-                 "OpenSSH_3.1*",       SSH_BUG_EXTEOF},
+                 "OpenSSH_3.1*",       SSH_BUG_EXTEOF|SSH_BUG_GSSAPI_BER},
+               { "OpenSSH_3.2*,"
+                 "OpenSSH_3.3*,"
+                 "OpenSSH_3.4*,"
+                 "OpenSSH_3.5*",       SSH_BUG_GSSAPI_BER},
                { "Sun_SSH_1.0*",       SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
                { "OpenSSH*",           0 },
                { "*MindTerm*",         0 },
index 881e450d39ea34682198a0ca1294e2612bc18f4e..75bc083dd054f8968caf390c054386a0575735a8 100644 (file)
@@ -56,6 +56,8 @@
 #define SSH_BUG_K5USER         0x00400000
 #define SSH_BUG_PROBE          0x00800000
 #define SSH_BUG_FIRSTKEX       0x01000000
+#define SSH_OLD_GSSAPI         0x02000000
+#define SSH_BUG_GSSAPI_BER     0x04000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
index ef937f13ccdb8284869db8ee413f944d75431ddd..9e6bdafb8f79825d84138978f6bd7b161f5f0fcb 100644 (file)
@@ -736,6 +736,7 @@ AC_ARG_WITH(pam,
                        AC_CHECK_LIB(dl, dlopen, , )
                        AC_CHECK_LIB(pam, pam_set_item, , AC_MSG_ERROR([*** libpam missing]))
                        AC_CHECK_FUNCS(pam_getenvlist)
+                       AC_CHECK_FUNCS(pam_putenv)
 
                        disable_shadow=yes
                        PAM_MSG="yes"
@@ -746,6 +747,7 @@ AC_ARG_WITH(pam,
                        else
                                LIBPAM="-lpam"
                        fi
+
                        AC_SUBST(LIBPAM)
                fi
        ]
@@ -776,6 +778,47 @@ if test "x$check_for_libcrypt_before" = "x1"; then
        AC_CHECK_LIB(crypt, crypt)
 fi
 
+# Start of GSI/Globus 2.0 mods
+# Check whether the user wants GSI (Globus 2.0) support
+# if we are using GSI, we will also use the 
+# OPenSSL that is built by Globus. This is called
+# -lcrypto_FLAVOR
+# and it will be in the GSI path. 
+# The includes will be in the include/FLAVOR/openssl
+# therfore we will not process the -with-ssl parameter.
+
+gsi_path="no"
+AC_ARG_WITH(gsi,
+    [  --with-gsi=PATH         Enable GSI/Globus GSSAPI support],
+    [
+        gsi_path="$withval"
+    ]
+)
+
+gsi_flavor=gcc32dbg
+AC_ARG_WITH(gsi-flavor,
+      [  --with-gsi-flavor=FLAVOR Globus build flavor ],
+      [
+              gsi_flavor="$withval"
+      ]
+)
+
+if test "x$gsi_path" != "xno" ; then
+    # Globus GSSAPI configuration
+    AC_DEFINE(GSSAPI)
+    AC_DEFINE(GSI)
+      AC_DEFINE(HAVE_OPENSSL)
+      LDFLAGS="$LDFLAGS -L${gsi_path}/lib"
+    if test ! -z "$need_dash_r" ; then
+        LDFLAGS="$LDFLAGS -R${gsi_path}/lib"
+    fi
+    if test ! -z "$blibpath" ; then
+        blibpath="$blibpath:${gsi_path}/lib"
+    fi
+      LIBS="$LIBS -lcrypto_${gsi_flavor} -lglobus_gss_assist_${gsi_flavor} -lglobus_gssapi_gsi_${gsi_flavor}"
+      CPPFLAGS="$CPPFLAGS -I${gsi_path}/include -I${gsi_path}/include/${gsi_flavor}"
+else
+
 # Search for OpenSSL
 saved_CPPFLAGS="$CPPFLAGS"
 saved_LDFLAGS="$LDFLAGS"
@@ -910,6 +953,8 @@ if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then
        AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt")
 fi
 
+fi
+#end of GSI/Globus 2.0 mods
 
 ### Configure cryptographic random number support
 
@@ -1831,6 +1876,31 @@ AC_ARG_WITH(kerberos5,
                         fi
                         AC_CHECK_LIB(resolv, dn_expand, , )
 
+                       AC_CHECK_LIB(gssapi,gss_init_sec_context,
+                               [ AC_DEFINE(GSSAPI)
+                                 K5LIBS="-lgssapi $K5LIBS" ],
+                               [ AC_CHECK_LIB(gssapi_krb5,gss_init_sec_context,
+                                       [ AC_DEFINE(GSSAPI)
+                                         K5LIBS="-lgssapi_krb5 $K5LIBS" ],
+                                       AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]),
+                                       $K5LIBS)
+                               ],
+                               $K5LIBS)
+                       
+                       AC_CHECK_HEADER(gssapi.h, ,
+                               [ unset ac_cv_header_gssapi_h
+                                 CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" 
+                                 AC_CHECK_HEADERS(gssapi.h, ,
+                                       AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
+                                 ) 
+                               ]
+                       )
+
+                       oldCPP="$CPPFLAGS"
+                       CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+                       AC_CHECK_HEADER(gssapi_krb5.h, ,
+                                       [ CPPFLAGS="$oldCPP" ])
+
                         KRB5=yes
                 fi
         ]
index b070ccf42eb2fb66402d6d511c19ec5e14628b4f..046b87a6e9cf2e2cc8a14bc2fc1622425e4d6f09 100644 (file)
@@ -42,6 +42,10 @@ RCSID("$OpenBSD: kex.c,v 1.55 2003/04/01 10:31:26 markus Exp $");
 #include "dispatch.h"
 #include "monitor.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #define KEX_COOKIE_LEN 16
 
 /* prototype */
@@ -295,6 +299,10 @@ choose_kex(Kex *k, char *client, char *server)
                k->kex_type = KEX_DH_GRP1_SHA1;
        } else if (strcmp(k->name, KEX_DHGEX) == 0) {
                k->kex_type = KEX_DH_GEX_SHA1;
+#ifdef GSSAPI
+       } else if (strncmp(k->name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) == 0) {
+               k->kex_type = KEX_GSS_GRP1_SHA1;
+#endif
        } else
                fatal("bad kex alg %s", k->name);
 }
index 52d442e9a7d19b39068f7cc534f714e01f215dca..d907e5ab10f86535dcacb1df7403a3e0de27f34f 100644 (file)
@@ -57,6 +57,7 @@ enum kex_modes {
 enum kex_exchange {
        KEX_DH_GRP1_SHA1,
        KEX_DH_GEX_SHA1,
+       KEX_GSS_GRP1_SHA1,
        KEX_MAX
 };
 
@@ -95,6 +96,11 @@ struct Newkeys {
        Mac     mac;
        Comp    comp;
 };
+
+struct KexOptions {
+       int     gss_deleg_creds;
+};
+
 struct Kex {
        u_char  *session_id;
        u_int   session_id_len;
@@ -108,8 +114,10 @@ struct Kex {
        Buffer  peer;
        int     done;
        int     flags;
+       char    *host;
        char    *client_version_string;
        char    *server_version_string;
+       struct  KexOptions options;
        int     (*verify_host_key)(Key *);
        Key     *(*load_host_key)(int);
        int     (*host_key_index)(Key *);
@@ -129,6 +137,10 @@ void        kexdh_client(Kex *);
 void    kexdh_server(Kex *);
 void    kexgex_client(Kex *);
 void    kexgex_server(Kex *);
+#ifdef GSSAPI
+void     kexgss_client(Kex *);
+void     kexgss_server(Kex *);
+#endif
 
 u_char *
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
index 060b63745a3d2762bbd5b9a14edf4bca8a54463d..22710045eca50f19184202258214c4189f6b4392 100644 (file)
@@ -646,6 +646,8 @@ key_type_from_name(char *name)
                return KEY_RSA;
        } else if (strcmp(name, "ssh-dss") == 0) {
                return KEY_DSA;
+       } else if (strcmp(name, "null") == 0){
+               return KEY_NULL;
        }
        debug2("key_type_from_name: unknown key type '%s'", name);
        return KEY_UNSPEC;
index 725c7a04a7bf2d6cfaf2a488be20c0381c11cbfe..4ad321f7eca4f80349d5bde74af217ab64f65285 100644 (file)
@@ -34,6 +34,7 @@ enum types {
        KEY_RSA1,
        KEY_RSA,
        KEY_DSA,
+       KEY_NULL,
        KEY_UNSPEC
 };
 enum fp_type {
index bcd007e607bf9eb23ab53fe68221390d24a14f50..32bc42436c45ac5151bcbfe62009b7e7bbd09428 100644 (file)
@@ -59,6 +59,11 @@ RCSID("$OpenBSD: monitor.c,v 1.36 2003/04/01 10:22:21 markus Exp $");
 #include "ssh2.h"
 #include "mpaux.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+static Gssctxt *gsscontext = NULL;
+#endif
+
 /* Imports */
 extern ServerOptions options;
 extern u_int utmp_len;
@@ -127,6 +132,14 @@ int mm_answer_krb4(int, Buffer *);
 int mm_answer_krb5(int, Buffer *);
 #endif
 
+#ifdef GSSAPI
+int mm_answer_gss_setup_ctx(int, Buffer *);
+int mm_answer_gss_accept_ctx(int, Buffer *);
+int mm_answer_gss_userok(int, Buffer *);
+int mm_answer_gss_sign(int, Buffer *);
+int mm_answer_gss_error(int, Buffer *);
+#endif
+
 static Authctxt *authctxt;
 static BIGNUM *ssh1_challenge = NULL;  /* used for ssh1 rsa auth */
 
@@ -171,6 +184,13 @@ struct mon_table mon_dispatch_proto20[] = {
 #ifdef SKEY
     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+    {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
 #endif
     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
     {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
@@ -178,6 +198,12 @@ struct mon_table mon_dispatch_proto20[] = {
 };
 
 struct mon_table mon_dispatch_postauth20[] = {
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error},
+#endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
@@ -267,6 +293,13 @@ monitor_child_preauth(struct monitor *pmonitor)
                /* Permit requests for moduli and signatures */
                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI          
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
+#endif
        } else {
                mon_dispatch = mon_dispatch_proto15;
 
@@ -1468,6 +1501,9 @@ mm_get_kex(Buffer *m)
        kex->we_need = buffer_get_int(m);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+       kex->kex[KEX_GSS_GRP1_SHA1] =kexgss_server;
+#endif
        kex->server = 1;
        kex->hostkey_type = buffer_get_int(m);
        kex->kex_type = buffer_get_int(m);
@@ -1648,3 +1684,117 @@ monitor_reinit(struct monitor *mon)
        mon->m_recvfd = pair[0];
        mon->m_sendfd = pair[1];
 }
+
+#ifdef GSSAPI
+
+int
+mm_answer_gss_setup_ctx(int socket, Buffer *m) {
+        gss_OID_desc oid;
+        OM_uint32 major;
+
+        oid.elements=buffer_get_string(m,&oid.length);
+                
+        major=ssh_gssapi_server_ctx(&gsscontext,&oid);
+
+        xfree(oid.elements);
+
+        buffer_clear(m);
+        buffer_put_int(m,major);
+
+        mm_request_send(socket,MONITOR_ANS_GSSSETUP,m);
+
+        return(0);
+}
+
+int
+mm_answer_gss_accept_ctx(int socket, Buffer *m) {
+        gss_buffer_desc in,out;
+        OM_uint32 major,minor;
+        OM_uint32 flags = 0; /* GSI needs this */
+
+        in.value = buffer_get_string(m,&in.length);
+        major=ssh_gssapi_accept_ctx(gsscontext,&in,&out,&flags);
+        xfree(in.value);
+
+        buffer_clear(m);
+        buffer_put_int(m, major);
+        buffer_put_string(m, out.value, out.length);
+        buffer_put_int(m, flags);
+        mm_request_send(socket,MONITOR_ANS_GSSSTEP,m);
+
+        gss_release_buffer(&minor, &out);
+
+        return(0);
+}
+int
+mm_answer_gss_userok(int socket, Buffer *m) {
+       int authenticated;
+
+        authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+
+        buffer_clear(m);
+        buffer_put_int(m, authenticated);
+
+        debug3("%s: sending result %d", __func__, authenticated);
+        mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m);
+
+       /* XXX - auth method could also be 'external' */
+       auth_method="gssapi";
+       
+        /* Monitor loop will terminate if authenticated */
+        return(authenticated);
+}
+
+int
+mm_answer_gss_sign(int socket, Buffer *m) {
+        gss_buffer_desc data,hash;
+        OM_uint32 major,minor;
+
+        data.value = buffer_get_string(m,&data.length);
+        if (data.length != 20)
+                fatal("%s: data length incorrect: %d", __func__, data.length);
+
+        /* Save the session ID - only first time round */
+        if (session_id2_len == 0) {
+                session_id2_len=data.length;
+                session_id2 = xmalloc(session_id2_len);
+                memcpy(session_id2, data.value, session_id2_len);
+        }
+        major=ssh_gssapi_sign(gsscontext, &data, &hash);
+
+        xfree(data.value);
+
+        buffer_clear(m);
+        buffer_put_int(m, major);
+        buffer_put_string(m, hash.value, hash.length);
+
+        mm_request_send(socket,MONITOR_ANS_GSSSIGN,m);
+
+        gss_release_buffer(&minor,&hash);
+
+       /* Turn on permissions for getpwnam */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+       
+        return(0);
+}
+
+int
+mm_answer_gss_error(int socket, Buffer *m) {
+        OM_uint32 major,minor;
+        char *msg;
+
+       msg=ssh_gssapi_last_error(gsscontext,&major,&minor);
+       buffer_clear(m);
+       buffer_put_int(m,major);
+       buffer_put_int(m,minor);
+       buffer_put_cstring(m,msg);
+
+       mm_request_send(socket,MONITOR_ANS_GSSERR,m);
+
+       xfree(msg);
+       
+        return(0);
+}
+
+
+#endif /* GSSAPI */
index 668ac98970dd383881837b3685233731710199d3..1bdddfc36126ba3d11529542774e1e7aa313776d 100644 (file)
@@ -39,6 +39,13 @@ enum monitor_reqtype {
        MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
        MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
        MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+#ifdef GSSAPI
+       MONITOR_REQ_GSSSETUP,MONITOR_ANS_GSSSETUP,
+       MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP,
+       MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN,
+       MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSERR,MONITOR_ANS_GSSERR,
+#endif
        MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
        MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
        MONITOR_REQ_KEYEXPORT,
index c9714138ada711a746f0f8f0d4f2123198c6cf42..a0c4d2a2f77f0216e36e01b1e51441b34ec0c1c6 100644 (file)
@@ -52,6 +52,10 @@ RCSID("$OpenBSD: monitor_wrap.c,v 1.24 2003/04/01 10:22:21 markus Exp $");
 #include "channels.h"
 #include "session.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* Imports */
 extern int compat20;
 extern Newkeys *newkeys[];
@@ -1019,3 +1023,108 @@ mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp)
        return (success);
 }
 #endif
+#ifdef GSSAPI
+OM_uint32
+mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) {
+        Buffer m;
+        OM_uint32 major;
+                
+        /* Client doesn't get to see the context */
+        *ctx=NULL;
+
+        buffer_init(&m);
+        buffer_put_string(&m,oid->elements,oid->length);
+
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
+
+        major=buffer_get_int(&m);
+
+       buffer_free(&m);
+        return(major);
+}
+
+OM_uint32
+mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
+                         gss_buffer_desc *out, OM_uint32 *flags) {
+        Buffer m;
+        OM_uint32 major;
+
+        buffer_init(&m);
+        buffer_put_string(&m, in->value, in->length);
+
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
+
+        major=buffer_get_int(&m);
+        out->value=buffer_get_string(&m,&out->length);
+        if (flags) *flags=buffer_get_int(&m);
+
+       buffer_free(&m);
+       
+        return(major);
+}
+
+int
+mm_ssh_gssapi_userok(char *user) {
+        Buffer m;
+        int authenticated = 0;
+
+        buffer_init(&m);
+        
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
+                                  &m);
+
+        authenticated = buffer_get_int(&m);
+
+        buffer_free(&m);
+        debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
+        return(authenticated);
+}
+
+OM_uint32
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) {
+        Buffer m;
+        OM_uint32 major;
+
+        buffer_init(&m);
+        buffer_put_string(&m, data->value, data->length);
+
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
+
+        major=buffer_get_int(&m);
+        hash->value = buffer_get_string(&m, &hash->length);
+
+       buffer_free(&m);
+       
+        return(major);
+}
+
+char *
+mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) {
+       Buffer m;
+       OM_uint32 maj,min;
+       char *errstr;
+       
+       buffer_init(&m);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m);
+
+       maj = buffer_get_int(&m);
+       min = buffer_get_int(&m);
+
+       if (major) *major=maj;
+       if (minor) *minor=min;
+       
+       errstr=buffer_get_string(&m,NULL);
+
+       buffer_free(&m);
+       
+       return(errstr);
+}      
+       
+#endif /* GSSAPI */
index d960a3d0b4c122d062d4296c8b428f88b542b17e..85173e194cd6c49ced695990cf864cc0a8abd3d2 100644 (file)
@@ -59,6 +59,17 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *);
 void mm_start_pam(char *);
 #endif
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctxt, gss_OID oid);
+OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctxt, gss_buffer_desc *recv,
+                                  gss_buffer_desc *send, OM_uint32 *flags);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *ctxt, gss_buffer_desc *buffer,
+                            gss_buffer_desc *hash);
+int mm_ssh_gssapi_userok(char *user);
+char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+#endif
+
 void mm_terminate(void);
 int mm_pty_allocate(int *, int *, char *, int);
 void mm_session_pty_cleanup2(void *);
index 1df5ce2d9b9d8d2210fc43972940e45fd8fed626..7bf3b08049fb3f6a81cc2f3841e7832d3160f615 100644 (file)
@@ -97,6 +97,12 @@ typedef enum {
 #if defined(KRB4) || defined(KRB5)
        oKerberosAuthentication,
 #endif
+#ifdef GSSAPI
+       oGssAuthentication, oGssDelegateCreds,
+#ifdef GSI
+       oGssGlobusDelegateLimitedCreds,
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(AFS) || defined(KRB5)
        oKerberosTgtPassing,
 #endif
@@ -144,6 +150,15 @@ static struct {
 #if defined(KRB4) || defined(KRB5)
        { "kerberosauthentication", oKerberosAuthentication },
 #endif
+#ifdef GSSAPI
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+#ifdef GSI
+       /* For backwards compatability with old 1.2.27 client code */
+       { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
+       { "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(AFS) || defined(KRB5)
        { "kerberostgtpassing", oKerberosTgtPassing },
 #endif
@@ -366,6 +381,23 @@ parse_flag:
                intptr = &options->kerberos_authentication;
                goto parse_flag;
 #endif
+#ifdef GSSAPI
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+      
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+#ifdef GSI
+       case oGssGlobusDelegateLimitedCreds:
+               intptr = &options->gss_globus_deleg_limited_proxy;
+               goto parse_flag;
+#endif /* GSI */
+
+#endif /* GSSAPI */
+
 #if defined(AFS) || defined(KRB5)
        case oKerberosTgtPassing:
                intptr = &options->kerberos_tgt_passing;
@@ -748,6 +780,14 @@ initialize_options(Options * options)
        options->rsa_authentication = -1;
        options->pubkey_authentication = -1;
        options->challenge_response_authentication = -1;
+#ifdef GSSAPI
+        options->gss_authentication = -1;
+        options->gss_deleg_creds = -1;
+#ifdef GSI
+        options->gss_globus_deleg_limited_proxy = -1;
+#endif /* GSI */
+#endif /* GSSAPI */
+
 #if defined(KRB4) || defined(KRB5)
        options->kerberos_authentication = -1;
 #endif
@@ -825,6 +865,16 @@ fill_default_options(Options * options)
                options->pubkey_authentication = 1;
        if (options->challenge_response_authentication == -1)
                options->challenge_response_authentication = 1;
+#ifdef GSSAPI
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 1;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 1;
+#ifdef GSI
+       if (options->gss_globus_deleg_limited_proxy == -1)
+               options->gss_globus_deleg_limited_proxy = 0;
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(KRB4) || defined(KRB5)
        if (options->kerberos_authentication == -1)
                options->kerberos_authentication = 1;
index 78e04fedf98b10729e33f44602daae5c3cc01a10..aad8c82c1c06aa5179d8a2d1012c1a75114819e2 100644 (file)
@@ -47,6 +47,15 @@ typedef struct {
 #if defined(AFS) || defined(KRB5)
        int     kerberos_tgt_passing;   /* Try Kerberos TGT passing. */
 #endif
+
+#ifdef GSSAPI
+       int     gss_authentication;
+       int     gss_deleg_creds;
+#ifdef GSI
+       int     gss_globus_deleg_limited_proxy;
+#endif /* GSI */
+#endif /* GSSAPI */
+
 #ifdef AFS
        int     afs_token_passing;      /* Try AFS token passing. */
 #endif
index 2510659ee4b916c9fb985c51e67deadb40cb3be8..f9b89960166b16d3ffbd87a97937a9b7d7020c52 100644 (file)
@@ -86,6 +86,12 @@ initialize_server_options(ServerOptions *options)
        options->hostbased_uses_name_from_packet_only = -1;
        options->rsa_authentication = -1;
        options->pubkey_authentication = -1;
+#ifdef GSSAPI
+       options->gss_authentication=-1;
+       options->gss_keyex=-1;
+       options->gss_use_session_ccache = -1;
+       options->gss_cleanup_creds = -1;
+#endif
 #if defined(KRB4) || defined(KRB5)
        options->kerberos_authentication = -1;
        options->kerberos_or_local_passwd = -1;
@@ -200,6 +206,16 @@ fill_default_server_options(ServerOptions *options)
                options->rsa_authentication = 1;
        if (options->pubkey_authentication == -1)
                options->pubkey_authentication = 1;
+#ifdef GSSAPI
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 1;
+       if (options->gss_keyex == -1)
+               options->gss_keyex =1;
+       if (options->gss_use_session_ccache == -1)
+               options->gss_use_session_ccache = 1;
+       if (options->gss_cleanup_creds == -1)
+               options->gss_cleanup_creds = 1;
+#endif
 #if defined(KRB4) || defined(KRB5)
        if (options->kerberos_authentication == -1)
                options->kerberos_authentication = 0;
@@ -280,6 +296,9 @@ typedef enum {
        sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
        sPermitRootLogin, sLogFacility, sLogLevel,
        sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
+#ifdef GSSAPI
+       sGssAuthentication, sGssKeyEx, sGssUseSessionCredCache, sGssCleanupCreds,
+#endif
 #if defined(KRB4) || defined(KRB5)
        sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 #endif
@@ -330,6 +349,13 @@ static struct {
        { "rsaauthentication", sRSAAuthentication },
        { "pubkeyauthentication", sPubkeyAuthentication },
        { "dsaauthentication", sPubkeyAuthentication },                 /* alias */
+#ifdef GSSAPI
+       { "gssapiauthentication", sGssAuthentication },
+       { "gssapikeyexchange", sGssKeyEx },
+       { "gssusesessionccache", sGssUseSessionCredCache },
+       { "gssapiusesessioncredcache", sGssUseSessionCredCache },
+       { "gssapicleanupcreds", sGssCleanupCreds },
+#endif
 #if defined(KRB4) || defined(KRB5)
        { "kerberosauthentication", sKerberosAuthentication },
        { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
@@ -645,6 +671,20 @@ parse_flag:
        case sPubkeyAuthentication:
                intptr = &options->pubkey_authentication;
                goto parse_flag;
+#ifdef GSSAPI
+       case sGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+       case sGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+       case sGssUseSessionCredCache:
+               intptr = &options->gss_use_session_ccache;
+               goto parse_flag;
+       case sGssCleanupCreds:
+               intptr = &options->gss_cleanup_creds;
+               goto parse_flag;
+#endif
 #if defined(KRB4) || defined(KRB5)
        case sKerberosAuthentication:
                intptr = &options->kerberos_authentication;
index 024987dd6983cfd8a743115e9451f29a97d6cc9b..1c947da6ce03b1794bc5cd83572b62b6e4015d27 100644 (file)
@@ -73,6 +73,13 @@ typedef struct {
        int     hostbased_uses_name_from_packet_only; /* experimental */
        int     rsa_authentication;     /* If true, permit RSA authentication. */
        int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. */
+       #ifdef GSSAPI
+       int     gss_authentication;
+       int     gss_keyex;
+       int     gss_use_session_ccache;        /* If true, delegated credentials are
+                                               * stored in a session specific cache */
+       int     gss_cleanup_creds;             /* If true, destroy cred cache on logout */
+#endif 
 #if defined(KRB4) || defined(KRB5)
        int     kerberos_authentication;        /* If true, permit Kerberos
                                                 * authentication. */
index c75fea9669330b60fff51c01ede0c957099a008d..7bab8900f1d01556a8d531567d52c6f1fec973b5 100644 (file)
@@ -58,6 +58,10 @@ RCSID("$OpenBSD: session.c,v 1.154 2003/03/05 22:33:43 markus Exp $");
 #include "session.h"
 #include "monitor_wrap.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #ifdef HAVE_CYGWIN
 #include <windows.h>
 #include <sys/cygwin.h>
@@ -455,6 +459,12 @@ do_exec_no_pty(Session *s, const char *command)
 
        session_proctitle(s);
 
+#if defined(GSSAPI)
+       temporarily_use_uid(s->pw);
+       ssh_gssapi_storecreds();
+       restore_uid();
+#endif
+
 #if defined(USE_PAM)
        do_pam_session(s->pw->pw_name, NULL);
        do_pam_setcred(1);
@@ -582,6 +592,12 @@ do_exec_pty(Session *s, const char *command)
        ptyfd = s->ptyfd;
        ttyfd = s->ttyfd;
 
+#if defined(GSSAPI)
+       temporarily_use_uid(s->pw);
+       ssh_gssapi_storecreds();
+       restore_uid();
+#endif
+
 #if defined(USE_PAM)
        do_pam_session(s->pw->pw_name, s->tty);
        do_pam_setcred(1);
@@ -840,7 +856,7 @@ check_quietlogin(Session *s, const char *command)
  * Sets the value of the given variable in the environment.  If the variable
  * already exists, its value is overriden.
  */
-static void
+void
 child_set_env(char ***envp, u_int *envsizep, const char *name,
        const char *value)
 {
@@ -967,6 +983,13 @@ do_setup_env(Session *s, const char *shell)
        copy_environment(environ, &env, &envsize);
 #endif
 
+#ifdef GSSAPI
+       /* Allow any GSSAPI methods that we've used to alter 
+       * the childs environment as they see fit
+       */
+       ssh_gssapi_do_child(&env,&envsize);
+#endif
+
        if (!options.use_login) {
                /* Set basic environment. */
                child_set_env(&env, &envsize, "USER", pw->pw_name);
@@ -2121,4 +2144,7 @@ static void
 do_authenticated2(Authctxt *authctxt)
 {
        server_loop2(authctxt);
+#if defined(GSSAPI)
+       ssh_gssapi_cleanup_creds(NULL);
+#endif
 }
index d3ddfab75f98644b7724986b02c26e193674dca3..012f0ff37439f7afa3b91c19c6f5ce2f49322e74 100644 (file)
@@ -68,4 +68,7 @@ Session       *session_new(void);
 Session        *session_by_tty(char *);
 void    session_close(Session *);
 void    do_setusercontext(struct passwd *);
+
+void   child_set_env(char ***envp, u_int *envsizep, const char *name,
+                      const char *value);
 #endif
index 642b34b9e49417563e75e119b3cfc38f625e72a2..cf193882742f5f4ff69f30068955af289bd715c3 100644 (file)
@@ -48,6 +48,10 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.114 2003/04/01 10:22:21 markus Exp $");
 #include "msg.h"
 #include "pathnames.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import */
 extern char *client_version_string;
 extern char *server_version_string;
@@ -77,10 +81,26 @@ void
 ssh_kex2(char *host, struct sockaddr *hostaddr)
 {
        Kex *kex;
+#ifdef GSSAPI
+       char *orig, *gss;
+       int len;
+#endif
 
        xxx_host = host;
        xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+       /* Add the GSSAPI mechanisms currently supported on this client to
+       * the key exchange algorithm proposal */
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+       gss = ssh_gssapi_client_mechanisms(host);
+       if (gss) {
+          len = strlen(orig)+strlen(gss)+2;
+          myproposal[PROPOSAL_KEX_ALGS]=xmalloc(len);
+          snprintf(myproposal[PROPOSAL_KEX_ALGS],len,"%s,%s",gss,orig);
+       }
+#endif
+
        if (options.ciphers == (char *)-1) {
                log("No valid ciphers for protocol version 2 given, using defaults.");
                options.ciphers = NULL;
@@ -108,14 +128,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
                    options.hostkeyalgorithms;
 
+#ifdef GSSAPI
+        /* If we've got GSSAPI algorithms, then we also support the
+         * 'null' hostkey, as a last resort */
+        if (gss) {
+                orig=myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+                len = strlen(orig)+sizeof(",null");
+                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]=xmalloc(len);
+                snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],len,"%s,null",orig);
+        }
+#endif
        /* start key exchange */
        kex = kex_setup(myproposal);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+#ifdef GSSAPI
+       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+#endif
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
        kex->verify_host_key=&verify_host_key_callback;
-
+       kex->host=host;
+#ifdef GSSAPI
+       kex->options.gss_deleg_creds=options.gss_deleg_creds;
+#endif
        xxx_kex = kex;
 
        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -160,6 +196,8 @@ struct Authctxt {
        Sensitive *sensitive;
        /* kbd-interactive */
        int info_req_seen;
+       /* generic */
+       void *methoddata;
 };
 struct Authmethod {
        char    *name;          /* string to compare against server's list */
@@ -182,6 +220,15 @@ int        userauth_passwd(Authctxt *);
 int    userauth_kbdint(Authctxt *);
 int    userauth_hostbased(Authctxt *);
 
+#ifdef GSSAPI
+int    userauth_external(Authctxt *authctxt);
+int    userauth_gssapi(Authctxt *authctxt);
+void   input_gssapi_response(int type, u_int32_t plen, void *ctxt);
+void   input_gssapi_token(int type, u_int32_t plen, void *ctxt);
+void   input_gssapi_hash(int type, u_int32_t plen, void *ctxt);
+void   input_gssapi_error(int, u_int32_t, void *);
+#endif
+
 void   userauth(Authctxt *, char *);
 
 static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *);
@@ -192,6 +239,16 @@ static Authmethod *authmethod_lookup(const char *name);
 static char *authmethods_get(void);
 
 Authmethod authmethods[] = {
+#ifdef GSSAPI
+       {"external-keyx",
+               userauth_external,
+               &options.gss_authentication,
+               NULL},
+       {"gssapi",
+               userauth_gssapi,
+               &options.gss_authentication,
+               NULL},
+#endif
        {"hostbased",
                userauth_hostbased,
                &options.hostbased_authentication,
@@ -256,6 +313,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
        authctxt.success = 0;
        authctxt.method = authmethod_lookup("none");
        authctxt.authlist = NULL;
+       authctxt.methoddata = NULL;
        authctxt.sensitive = sensitive;
        authctxt.info_req_seen = 0;
        if (authctxt.method == NULL)
@@ -278,6 +336,11 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
 void
 userauth(Authctxt *authctxt, char *authlist)
 {
+       if (authctxt->methoddata!=NULL) {
+               xfree(authctxt->methoddata);
+               authctxt->methoddata=NULL;
+       }
+           
        if (authlist == NULL) {
                authlist = authctxt->authlist;
        } else {
@@ -327,6 +390,8 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
                fatal("input_userauth_success: no authentication context");
        if (authctxt->authlist)
                xfree(authctxt->authlist);
+       if (authctxt->methoddata)
+               xfree(authctxt->methoddata);
        clear_auth_state(authctxt);
        authctxt->success = 1;                  /* break out */
 }
@@ -428,6 +493,219 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
 
 }
 
+#ifdef GSSAPI
+int 
+userauth_gssapi(Authctxt *authctxt)
+{
+       Gssctxt *gssctxt = NULL;
+       static gss_OID_set supported = NULL;
+       static int mech=0;
+       OM_uint32 min;
+       int ok=0;
+
+       /* Things work better if we send one mechanism at a time, rather
+       * than them all at once. This means that if we fail at some point
+       * in the middle of a negotiation, we can come back and try something
+       * different. */
+
+       if (datafellows & SSH_OLD_GSSAPI) return 0;
+       
+       /* Before we offer a mechanism, check that we can support it. Don't
+       * bother trying to get credentials - as the standard fallback will
+       * deal with that kind of failure.
+       */
+
+       if (supported==NULL) gss_indicate_mechs(&min, &supported);
+       
+       while (mech<supported->count && !ok) {
+               if (gssctxt) ssh_gssapi_delete_ctx(&gssctxt);
+               ssh_gssapi_build_ctx(&gssctxt);
+               ssh_gssapi_set_oid(gssctxt,&supported->elements[mech]);
+
+               /* The DER encoding below only works for lengths<128,
+               * so check this here 
+               */
+               if (supported->elements[mech].length<128 &&
+                   !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
+                                                     authctxt->host))) {
+                       ok = 1; /* Mechanism works */
+               } else {
+                       mech++;
+               }
+       }
+       
+       if (!ok) return 0;
+       
+       authctxt->methoddata=(void *)gssctxt;
+               
+       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_int(1);
+
+       /* The newest gsskeyex draft stipulates that OIDs should
+       * be DER encoded, so we need to add the object type and
+       * length information back on */
+       if (datafellows & SSH_BUG_GSSAPI_BER) {
+               packet_put_string(supported->elements[mech].elements,
+                                 supported->elements[mech].length);
+       } else {
+               packet_put_int((supported->elements[mech].length)+2);
+               packet_put_char(0x06);
+               packet_put_char(supported->elements[mech].length);
+               packet_put_raw(supported->elements[mech].elements,
+                              supported->elements[mech].length);
+       }
+
+        packet_send();
+        packet_write_wait();
+
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response);
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,&input_gssapi_token);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,&input_gssapi_error);
+       
+       mech++; /* Move along to next candidate */
+
+        return 1;
+}
+
+void
+input_gssapi_response(int type, u_int32_t plen, void *ctxt) 
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       OM_uint32 status,ms;
+       int oidlen;
+       char *oidv;
+       gss_buffer_desc send_tok;
+       
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+       
+       /* Setup our OID */
+       oidv=packet_get_string(&oidlen);
+       
+       if (datafellows & SSH_BUG_GSSAPI_BER) {
+               if (!ssh_gssapi_check_oid(gssctxt,oidv,oidlen)) {
+                       fatal("Server returned different OID than expected");
+               }
+               ssh_gssapi_set_oid_data(gssctxt,oidv,oidlen);
+       } else {
+               if(oidv[0]!=0x06 || oidv[1]!=oidlen-2) {
+                       debug("Badly encoded mechanism OID received");
+                       clear_auth_state(authctxt);
+                       userauth(authctxt,NULL);
+                       return;
+               }
+               if (!ssh_gssapi_check_oid(gssctxt,oidv+2,oidlen-2)) {
+                       fatal("Server returned different OID than expected");
+               }
+               ssh_gssapi_set_oid_data(gssctxt,oidv+2,oidlen-2);
+       }
+               
+       packet_check_eom();
+       
+       status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+                                    GSS_C_NO_BUFFER, &send_tok, 
+                                    NULL);
+       if (GSS_ERROR(status)) {
+               /* Start again with next method on list */
+               debug("Trying to start again");
+               clear_auth_state(authctxt);
+               userauth(authctxt,NULL);
+               return;
+       }
+
+       /* We must have data to send */                                 
+       packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+       packet_put_string(send_tok.value,send_tok.length);
+       packet_send();
+       packet_write_wait();
+       gss_release_buffer(&ms, &send_tok);
+}
+
+void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       gss_buffer_desc send_tok,recv_tok;
+       OM_uint32 status;
+       
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+       
+       recv_tok.value=packet_get_string(&recv_tok.length);
+
+       status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+                                  &recv_tok, &send_tok, NULL);
+
+       packet_check_eom();
+       
+       if (GSS_ERROR(status)) {
+               /* Start again with the next method in the list */
+               clear_auth_state(authctxt);
+               userauth(authctxt,NULL);
+               return;
+       }
+       
+       if (send_tok.length>0) {
+               packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+               packet_put_string(send_tok.value,send_tok.length);
+               packet_send();
+               packet_write_wait();
+       }
+       
+       if (status == GSS_S_COMPLETE) {
+               /* If that succeeded, send a exchange complete message */
+               packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
+               packet_send();
+               packet_write_wait();
+       }
+}
+
+void
+input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+{
+       OM_uint32 maj,min;
+       char *msg;
+       char *lang;
+       
+       maj=packet_get_int();
+       min=packet_get_int();
+       msg=packet_get_string(NULL);
+       lang=packet_get_string(NULL);
+
+       packet_check_eom();
+       
+       fprintf(stderr, "Server GSSAPI Error:\n%s\n", msg);
+       xfree(msg);
+       xfree(lang);
+}
+
+int
+userauth_external(Authctxt *authctxt)
+{
+        static int attempt =0;
+        
+        if (attempt++ >= 1)
+               return 0;
+                                
+        debug2("userauth_external");
+        packet_start(SSH2_MSG_USERAUTH_REQUEST);
+        packet_put_cstring(authctxt->server_user);
+        packet_put_cstring(authctxt->service);
+        packet_put_cstring(authctxt->method->name);
+        packet_send();
+        packet_write_wait();
+        return 1;
+}                                                                                                
+#endif /* GSSAPI */
+
 int
 userauth_none(Authctxt *authctxt)
 {
@@ -438,6 +716,7 @@ userauth_none(Authctxt *authctxt)
        packet_put_cstring(authctxt->method->name);
        packet_send();
        return 1;
+
 }
 
 int
@@ -544,7 +823,12 @@ clear_auth_state(Authctxt *authctxt)
 {
        /* XXX clear authentication state */
        dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
-
+#ifdef GSSAPI
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,NULL);
+#endif
+       
        if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
                debug3("clear_auth_state: key_free %p", authctxt->last_key);
                key_free(authctxt->last_key);
index 0f2b2a3ce597496363d99d3b2d873be10981bced..c595b28127afde560cfb2a3986f75b93818724be 100644 (file)
@@ -85,6 +85,10 @@ RCSID("$OpenBSD: sshd.c,v 1.263 2003/02/16 17:09:57 markus Exp $");
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #ifdef LIBWRAP
 #include <tcpd.h>
 #include <syslog.h>
@@ -1013,10 +1017,13 @@ main(int ac, char **av)
                log("Disabling protocol version 1. Could not load host key");
                options.protocol &= ~SSH_PROTO_1;
        }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
        if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
                log("Disabling protocol version 2. Could not load host key");
                options.protocol &= ~SSH_PROTO_2;
        }
+#endif
        if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
                log("sshd: no hostkeys available -- exiting.");
                exit(1);
@@ -1816,10 +1823,52 @@ do_ssh2_kex(void)
        }
        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
+#ifdef GSSAPI
+       { 
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+               orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* If we don't have a host key, then all of the algorithms
+       * currently in myproposal are useless */
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])==0)
+               orig= NULL;
+               
+        if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+        else
+               gss = NULL;
+        
+       if (gss && orig) {
+               int len = strlen(orig) + strlen(gss) +2;
+               newstr=xmalloc(len);
+               snprintf(newstr,len,"%s,%s",gss,orig);
+       } else if (gss) {
+               newstr=gss;
+       } else if (orig) {
+               newstr=orig;
+       }
+        /* If we've got GSSAPI mechanisms, then we've also got the 'null'
+          host key algorithm, but we're not allowed to advertise it, unless
+          its the only host key algorithm we're supporting */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) {
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]="null";
+       }
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS]=newstr;
+       else
+               fatal("No supported key exchange algorithms");
+        }
+#endif
+
        /* start key exchange */
        kex = kex_setup(myproposal);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+        kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+#endif         
        kex->server = 1;
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
index 6f38a260aa4e075b5d74bb9de4366f86b2a068b0..93124e53496fda3860e25779957286514636f2bd 100644 (file)
@@ -253,6 +253,26 @@ keys are used for version 1 and
 or
 .Dq rsa
 are used for version 2 of the SSH protocol.
+.It Cm GssapiAuthentication
+Specifies whether authentication based on GSSAPI may be used, either using
+the result of a successful key exchange, or using GSSAPI user
+authentication.
+The default is 
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GssapiKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GssapiUseSessionCredCache
+Specifies whether a unique credentials cache name should be generated per
+session for storing delegated credentials.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+
 .It Cm IgnoreRhosts
 Specifies that
 .Pa .rhosts
This page took 0.198972 seconds and 5 git commands to generate.