]> andersk Git - gssapi-openssh.git/commitdiff
merge with OPENSSH_3_6_1P1_SIMON_20030417 OPENSSH_3_6_1P1_GSSAPI_20030421
authorjbasney <jbasney>
Mon, 21 Apr 2003 20:22:05 +0000 (20:22 +0000)
committerjbasney <jbasney>
Mon, 21 Apr 2003 20:22:05 +0000 (20:22 +0000)
openssh/auth2-gss.c
openssh/gss-genr.c
openssh/gss-serv.c
openssh/kexgssc.c
openssh/kexgsss.c
openssh/monitor.c
openssh/monitor.h
openssh/monitor_wrap.c
openssh/monitor_wrap.h
openssh/ssh-gss.h
openssh/sshconnect2.c

index 6d08d80023813df8274a6235673582d8f9b99f4b..4204528cc64682966f8e063688a296c28de298fb 100644 (file)
@@ -52,6 +52,7 @@ userauth_external(Authctxt *authctxt)
 static void ssh_gssapi_userauth_error(Gssctxt *ctxt);
 static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
+static void input_gssapi_errtok(int, u_int32_t, void *);
 
 /* We only support those mechanisms that we know about (ie ones that we know
  * how to check local user kuserok and the like
@@ -93,22 +94,15 @@ userauth_gssapi(Authctxt *authctxt)
                 doid = packet_get_string(&len);
                 debug("Got string");
                 
-                if (datafellows & SSH_BUG_GSSAPI_BER) {
-                       oid.elements = doid;
-                       oid.length = len;
-                } else {
-                       if (doid[0]!=0x06 || doid[1]!=len-2) {
-                               debug("Badly encoded mechanism OID received");
-                               oid.elements=NULL;
-                       } else {
-                               oid.elements = doid + 2;
-                               oid.length   = len - 2;
-                               gss_test_oid_set_member(&ms, &oid, supported, &present);
-                       }
-                }
-               if (oid.elements) {
-                       gss_test_oid_set_member(&ms, &oid, supported, &present);
-               }
+                       if (doid[0]!=0x06 || doid[1]!=len-2) {
+                               log("Mechanism OID received using the old encoding form");
+                               oid.elements = doid;
+                               oid.length = len;
+                       } else {
+                               oid.elements = doid + 2;
+                               oid.length   = len - 2;
+                       }
+               gss_test_oid_set_member(&ms, &oid, supported, &present);
         } while (mechs>0 && !present);
         
         if (!present) {
@@ -134,11 +128,8 @@ userauth_gssapi(Authctxt *authctxt)
 
                packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
 
-       if (datafellows & SSH_BUG_GSSAPI_BER) {
-                       packet_put_string(oid.elements,oid.length);
-               } else {
-                       packet_put_string(doid,len);
-               }
+       /* Just return whatever they sent */
+       packet_put_string(doid,len);
 
        } /* !compat20 */
                
@@ -152,6 +143,8 @@ userauth_gssapi(Authctxt *authctxt)
        else
         dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, 
                      &input_gssapi_token);
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,
+                    &input_gssapi_errtok);
         authctxt->postponed = 1;
         
         return 0;
@@ -174,41 +167,74 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
         recv_tok.length=len; /* int vs. size_t */
         
         maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 
-                                               &send_tok, NULL));
+                                                &send_tok, NULL));
         packet_check_eom();
                         
-        if (send_tok.length != 0) {
-                /* Send a packet back to the client, even if there has
-                 * been an error, as this may contain mechanism specific
-                 * error information */
-               if (!compat20)
-               packet_start(SSH_MSG_AUTH_GSSAPI_TOKEN);
-               else
-               packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
-                packet_put_string(send_tok.value,send_tok.length);
-                packet_send();
-                packet_write_wait();
-                gss_release_buffer(&min_status, &send_tok);        
-        }
-       
         if (GSS_ERROR(maj_status)) {
-                ssh_gssapi_userauth_error(gssctxt);
+               ssh_gssapi_userauth_error(gssctxt);
+               if (send_tok.length != 0) {
+                   if (!compat20)
+                       packet_start(SSH_MSG_AUTH_GSSAPI_TOKEN);
+                   else
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+                       packet_put_string(send_tok.value,send_tok.length);
+                       packet_send();
+                               packet_write_wait();
+                       }
                 authctxt->postponed = 0;
                dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
                 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
                 userauth_finish(authctxt, 0, "gssapi");
+        } else {
+                       if (send_tok.length != 0) {
+                   if (!compat20)
+                       packet_start(SSH_MSG_AUTH_GSSAPI_TOKEN);
+                   else
+                               packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+                               packet_put_string(send_tok.value,send_tok.length);
+                               packet_send();
+                               packet_write_wait();
+                }
+               if (maj_status == GSS_S_COMPLETE) {
+                       dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
+                       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
+                       if (!compat20)
+                       input_gssapi_exchange_complete(0, 0, ctxt);
+                       else
+                       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
+                                    &input_gssapi_exchange_complete);
+                }
         }
+        
+        gss_release_buffer(&min_status, &send_tok);        
+}
 
-        if (maj_status == GSS_S_COMPLETE) {
-               dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
-                dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
-               /* ssh1 does not have an extra message here */
-               if (!compat20)
-               input_gssapi_exchange_complete(0, 0, ctxt);
-               else
-               dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
-                            &input_gssapi_exchange_complete);
-        }
+static void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+        Authctxt *authctxt = ctxt;
+        Gssctxt *gssctxt;
+        gss_buffer_desc send_tok,recv_tok;
+        OM_uint32 maj_status;
+        
+        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+                fatal("No authentication or GSSAPI context");
+                
+        gssctxt=authctxt->methoddata;
+        recv_tok.value=packet_get_string(&recv_tok.length);
+        
+        /* Push the error token into GSSAPI to see what it says */
+        maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 
+                                                &send_tok, NULL));
+        packet_check_eom();
+
+       /* We can't return anything to the client, even if we wanted to */
+       dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,NULL);
+
+       /* The client will have already moved on to the next auth */
+       
 }
 
 /* This is called when the client thinks we've completed authentication.
@@ -282,6 +308,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 finish:
         authctxt->postponed = 0;
         dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
         dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
         userauth_finish(authctxt, authenticated, "gssapi");
 }
@@ -292,6 +319,9 @@ static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
        
        errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
        if (errstr) {
+           if (!compat20) {
+               packet_send_debug(errstr);
+           } else {
                packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR);
                packet_put_int(maj);
                packet_put_int(min);
@@ -300,6 +330,7 @@ static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
                packet_send();
                packet_write_wait();
                xfree(errstr);
+           }
        }
 }
 
index e91dc398c4f0371543227e1a61fa57d4038346a3..f0a160b965a116ff009907ba010327725bfa6080 100644 (file)
@@ -99,10 +99,10 @@ ssh_gssapi_client_mechanisms(char *host) {
                    ssh_gssapi_check_mechanism(&(supported->elements[i]),host)) {
 
                        /* Earlier versions of this code interpreted the
-                       * spec incorrectly with regard to OID encoding. They
-                       * also mis-encoded the krb5 OID. The following
-                       * _temporary_ code interfaces with these broken
-                       * servers */
+                        * spec incorrectly with regard to OID encoding. They
+                        * also mis-encoded the krb5 OID. The following
+                        * _temporary_ code interfaces with these broken
+                        * servers */
 
                        if (datafellows & SSH_BUG_GSSAPI_BER) {
                                char *bodge=NULL;
@@ -143,8 +143,8 @@ ssh_gssapi_client_mechanisms(char *host) {
                        EVP_DigestInit(&md, evp_md);
                        EVP_DigestUpdate(&md,deroid,2);
                        EVP_DigestUpdate(&md,
-                                       supported->elements[i].elements,
-                                       supported->elements[i].length);
+                                        supported->elements[i].elements,
+                                        supported->elements[i].length);
                        EVP_DigestFinal(&md, digest, NULL);
                        
                        /* Base64 encode it */
@@ -376,11 +376,11 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) {
        char *xhost;
        
        /* Make a copy of the host name, in case it was returned by a
-       * previous call to gethostbyname(). */  
+        * previous call to gethostbyname(). */ 
        xhost = xstrdup(host);
 
        /* Make sure we have the FQDN. Some GSSAPI implementations don't do
-       * this for us themselves */
+        * this for us themselves */
        resolve_localhost(&xhost);
        
         gssbuf.length = sizeof("host@")+strlen(xhost);
@@ -426,7 +426,7 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) {
        }
        
        if ((ctx->major=gss_acquire_cred(&ctx->minor,
-                                   ctx->name,
+                                   ctx->name,
                                    0,
                                    oidset,
                                    GSS_C_ACCEPT,
index b94472eaf34fae2e286ecd7ea64b50ccd735c874..39cdb3f6933404040e6caae06e6736931ce06d81 100644 (file)
@@ -93,7 +93,8 @@ ssh_gssapi_mech* supported_mechs[]= {
  * that stores the results (in an expanded Gssctxt structure), which are
  * then used by the first calls if that key exchange mechanism is chosen.
  */
+
+/* Unpriviledged */ 
 char * 
 ssh_gssapi_server_mechanisms() {
        gss_OID_set     supported;
@@ -156,6 +157,7 @@ ssh_gssapi_server_mechanisms() {
           return(mechs);
 }
 
+/* Unpriviledged */
 void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
        int i =0;
        OM_uint32 maj_status,min_status;
@@ -184,6 +186,8 @@ void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
 /* Find out which GSS type (out of the list we define in ssh-gss.h) a
  * particular connection is using 
  */
+
+/* Priviledged (called ssh_gssapi_accept_ctx -> ssh_gssapi_getclient ->) */
 ssh_gssapi_mech *
 ssh_gssapi_get_ctype(Gssctxt *ctxt) {
        int i=0;
@@ -199,11 +203,11 @@ ssh_gssapi_get_ctype(Gssctxt *ctxt) {
        return NULL;
 }
 
-/* Set the GSS context's OID to the oid indicated by the given key exchange
- * name. */
+/* Return the OID that corresponds to the given context name */
  
+/* Unpriviledged */
 gss_OID 
-ssh_gssapi_id_kex(Gssctxt *ctx, char *name) {
+ssh_gssapi_server_id_kex(char *name) {
   int i=0;
   
   if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) {
@@ -213,26 +217,25 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name) {
   name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the MIME string */
   
   while (supported_mechs[i]->name!=NULL &&
-       strcmp(name,supported_mechs[i]->enc_name)!=0) {
+        strcmp(name,supported_mechs[i]->enc_name)!=0) {
        i++;
   }
 
   if (supported_mechs[i]->name==NULL)
      return (NULL);
 
-  if (ctx) ssh_gssapi_set_oid(ctx,&supported_mechs[i]->oid);
-
   debug("using GSSAPI mechanism %s (%s%s)", supported_mechs[i]->name,
        KEX_GSS_SHA1, supported_mechs[i]->enc_name);
 
   return &supported_mechs[i]->oid;
 }
 
-/* Wrapper arround accept_sec_context
+/* Wrapper around accept_sec_context
  * Requires that the context contains:
  *    oid              
  *    credentials      (from ssh_gssapi_acquire_cred)
  */
+/* Priviledged */
 OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
                                gss_buffer_desc *send_tok, OM_uint32 *flags) 
 {
@@ -261,13 +264,13 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
        }
 
        /* FIXME: We should check that the me
-       * the one that we asked for (in ctx->oid) */
+        * the one that we asked for (in ctx->oid) */
 
        status=ctx->major;
        
        /* Now, if we're complete and we have the right flags, then
-       * we flag the user as also having been authenticated
-       */
+        * we flag the user as also having been authenticated
+        */
        
        if (((flags==NULL) || ((*flags & GSS_C_MUTUAL_FLAG) && 
                               (*flags & GSS_C_INTEG_FLAG))) &&
@@ -285,6 +288,7 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
 /* Extract the client details from a given context. This can only reliably
  * be called once for a context */
 
+/* Priviledged (called from accept_secure_ctx) */
 OM_uint32 
 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_mech **type,
                     gss_buffer_desc *name, gss_cred_id_t *creds) {
@@ -296,14 +300,15 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_mech **type,
        }
        
        /* This is icky. There appears to be no way to copy this structure,
-       * rather than the pointer to it, so we simply copy the pointer and
-       * mark the originator as empty so we don't destroy it. 
-       */
+        * rather than the pointer to it, so we simply copy the pointer and
+        * mark the originator as empty so we don't destroy it. 
+        */
        *creds=ctx->client_creds;
        ctx->client_creds=GSS_C_NO_CREDENTIAL;
        return(ctx->major);
 }
 
+/* As user - called through fatal cleanup hook */
 void
 ssh_gssapi_cleanup_creds(void *ignored)
 {
@@ -314,6 +319,7 @@ ssh_gssapi_cleanup_creds(void *ignored)
        }
 }
 
+/* As user */
 void 
 ssh_gssapi_storecreds()
 {
@@ -329,10 +335,8 @@ ssh_gssapi_storecreds()
 
 /* This allows GSSAPI methods to do things to the childs environment based
  * on the passed authentication process and credentials.
- *
- * Question: If we didn't use userauth_external for some reason, should we
- * still delegate credentials?
  */
+/* As user */
 void 
 ssh_gssapi_do_child(char ***envp, u_int *envsizep) 
 {
@@ -347,6 +351,7 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep)
        }
 }
 
+/* Priviledged */
 int
 ssh_gssapi_userok(char *user)
 {
@@ -363,6 +368,7 @@ ssh_gssapi_userok(char *user)
        return(0);
 }
 
+/* Priviledged */
 int
 ssh_gssapi_localname(char **user)
 {
index 7e3729eea6edf2b6a934cde34cd9a232d5713e86..67b654170c1eea667fb1860ef40532bff1126401 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001,2002 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -82,7 +82,7 @@ kexgss_client(Kex *kex)
        }
                
        token_ptr = GSS_C_NO_BUFFER;
-                       
+                        
        do {
                debug("Calling gss_init_sec_context");
                
@@ -92,8 +92,14 @@ kexgss_client(Kex *kex)
                                               &ret_flags);
 
                if (GSS_ERROR(maj_status)) {
+                       if (send_tok.length!=0) {
+                               /* Hmmm - not sure about this */
+                               packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                               packet_put_string(send_tok.value,
+                                                 send_tok.length);
+                       }                         
                        fatal("gss_init_context failed");
-               } 
+               }
 
                /* If we've got an old receive buffer get rid of it */
                if (token_ptr != GSS_C_NO_BUFFER)
@@ -171,14 +177,18 @@ kexgss_client(Kex *kex)
                                min_status=packet_get_int();
                                msg=packet_get_string(NULL);
                                lang=packet_get_string(NULL);
-                               fatal(msg);
+                               fprintf(stderr,"GSSAPI Error: \n%s",msg);
                        default:
                                packet_disconnect("Protocol error: didn't expect packet type %d",
                                type);
                        }
                        token_ptr=&recv_tok;
+               } else {
+                       /* No data, and not complete */
+                       if (maj_status!=GSS_S_COMPLETE) {
+                               fatal("Not complete, and no token output");
+                       }
                }
-
        } while (maj_status & GSS_S_CONTINUE_NEEDED);
        
        /* We _must_ have received a COMPLETE message in reply from the 
index 7cb068da008721aedc1c2c5b70cd1be003c39395..b4e0f2cd9eee7ccb067bbcad9bea951c27f4a96d 100644 (file)
@@ -48,9 +48,9 @@ kexgss_server(Kex *kex)
        OM_uint32 maj_status, min_status;
        
        /* Some GSSAPI implementations use the input value of ret_flags (an
-       * output variable) as a means of triggering mechanism specific 
-       * features. Initializing it to zero avoids inadvertently 
-       * activating this non-standard behaviour.*/
+        * output variable) as a means of triggering mechanism specific 
+        * features. Initializing it to zero avoids inadvertently 
+        * activating this non-standard behaviour.*/
 
        OM_uint32 ret_flags = 0;
        gss_buffer_desc gssbuf,send_tok,recv_tok,msg_tok;
@@ -68,7 +68,7 @@ kexgss_server(Kex *kex)
        /* Initialise GSSAPI */
 
        debug2("%s: Identifying %s",__func__,kex->name);
-       oid=ssh_gssapi_id_kex(ctxt,kex->name);
+       oid=ssh_gssapi_server_id_kex(kex->name);
        if (oid==NULL) {
           packet_disconnect("Unknown gssapi mechanism");
        }
@@ -99,8 +99,6 @@ kexgss_server(Kex *kex)
                        /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
                        break;
                case SSH2_MSG_KEXGSS_CONTINUE:
-                       if (dh_client_pub == NULL)
-                               packet_disconnect("Received KEXGSS_CONTINUE without initialising");
                        recv_tok.value=packet_get_string(&slen);
                        recv_tok.length=slen; /* int vs. size_t */
                        break;
@@ -110,7 +108,7 @@ kexgss_server(Kex *kex)
                }
                
                maj_status=PRIVSEP(ssh_gssapi_accept_ctx(ctxt,&recv_tok, 
-                                                       &send_tok, &ret_flags));
+                                                        &send_tok, &ret_flags));
 
                gss_release_buffer(&min_status,&recv_tok);
                
@@ -120,8 +118,14 @@ kexgss_server(Kex *kex)
                 }
 #endif
 
-               if ((maj_status & GSS_S_CONTINUE_NEEDED) ||
-                   (GSS_ERROR(maj_status) && send_tok.length>0)) {
+               if (maj_status!=GSS_S_COMPLETE && send_tok.length==0) {
+                       fatal("Zero length token output when incomplete");
+               }
+
+               if (dh_client_pub == NULL)
+                       fatal("No client public key");
+               
+               if (maj_status & GSS_S_CONTINUE_NEEDED) {
                        debug("Sending GSSAPI_CONTINUE");
                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
                        packet_put_string(send_tok.value,send_tok.length);
@@ -133,6 +137,12 @@ kexgss_server(Kex *kex)
 
        if (GSS_ERROR(maj_status)) {
                kex_gss_send_error(ctxt);
+               if (send_tok.length>0) {
+                       packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                       packet_put_string(send_tok.value,send_tok.length);
+                       packet_send();
+                       packet_write_wait();
+               }       
                packet_disconnect("gssapi key exchange handshake failed");
        }
        
@@ -206,7 +216,7 @@ kexgss_server(Kex *kex)
        gss_release_buffer(&min_status, &send_tok);     
 
        /* If we've got a context, delete it. It may be NULL if we've been
-       * using privsep */
+        * using privsep */
        ssh_gssapi_delete_ctx(&ctxt);
        
        DH_free(dh);
index e36cc23571dea8a25306d206865ce073ca6d3e94..95b67b849d8235dc23d4921840b3952c23dc9894 100644 (file)
@@ -138,8 +138,9 @@ int mm_answer_gss_accept_ctx(int, Buffer *);
 int mm_answer_gss_userok(int, Buffer *);
 int mm_answer_gss_localname(int, Buffer *);
 int mm_answer_gss_sign(int, Buffer *);
-int mm_answer_gss_indicate_mechs(int, Buffer *);
 int mm_answer_gss_error(int, Buffer *);
+int mm_answer_gss_indicate_mechs(int, Buffer *);
+int mm_answer_gss_localname(int, Buffer *);
 #endif
 
 #ifdef GSI
@@ -195,10 +196,10 @@ struct mon_table mon_dispatch_proto20[] = {
     {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_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
     {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
-    {MONITOR_REQ_GSSLOCALNAME, MON_AUTH, mm_answer_gss_localname},
-    {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
+    {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
 #endif
     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
     {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
@@ -210,8 +211,8 @@ struct mon_table mon_dispatch_postauth20[] = {
     {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_GSSMECHS, 0, mm_answer_gss_indicate_mechs},
     {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error},
+    {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs},
 #endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
@@ -321,17 +322,14 @@ monitor_child_preauth(struct monitor *pmonitor)
 #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_GSSMECHS, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1);
 #endif
        } else {
                mon_dispatch = mon_dispatch_proto15;
 
                monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
 #ifdef GSSAPI          
-               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
 #endif
@@ -388,6 +386,13 @@ monitor_child_postauth(struct monitor *pmonitor)
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
 
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1);
+#endif
+
        } else {
                mon_dispatch = mon_dispatch_postauth15;
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@@ -1740,6 +1745,9 @@ mm_answer_gss_setup_ctx(int socket, Buffer *m) {
 
         mm_request_send(socket,MONITOR_ANS_GSSSETUP,m);
 
+       /* Now we have a context, enable the step and sign */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,1);
+
         return(0);
 }
 
@@ -1761,8 +1769,14 @@ mm_answer_gss_accept_ctx(int socket, Buffer *m) {
 
         gss_release_buffer(&minor, &out);
 
+       /* Complete - now we can do signing */
+       if (major==GSS_S_COMPLETE) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,0);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN,1);            
+       }
         return(0);
 }
+
 int
 mm_answer_gss_userok(int socket, Buffer *m) {
        int authenticated;
@@ -1782,27 +1796,6 @@ mm_answer_gss_userok(int socket, Buffer *m) {
         return(authenticated);
 }
 
-int
-mm_answer_gss_localname(int socket, Buffer *m) {
-       char *name;
-
-       ssh_gssapi_localname(&name);
-
-        buffer_clear(m);
-       if (name) {
-           buffer_put_cstring(m, name);
-           debug3("%s: sending result %s", __func__, name);
-           xfree(name);
-       } else {
-           buffer_put_cstring(m, "");
-           debug3("%s: sending result \"\"", __func__);
-       }
-
-        mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m);
-
-        return(0);
-}
-
 int
 mm_answer_gss_sign(int socket, Buffer *m) {
         gss_buffer_desc data,hash;
@@ -1838,6 +1831,24 @@ mm_answer_gss_sign(int socket, Buffer *m) {
         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);
+}
+
 int
 mm_answer_gss_indicate_mechs(int socket, Buffer *m) {
         OM_uint32 major,minor;
@@ -1854,29 +1865,35 @@ mm_answer_gss_indicate_mechs(int socket, Buffer *m) {
                              mech_set->elements[i].length);
        }
 
+#if !defined(MECHGLUE) /* mechglue memory management bug ??? */
+       gss_release_oid_set(&minor,&mech_set);
+#endif
+       
        mm_request_send(socket,MONITOR_ANS_GSSMECHS,m);
 
        return(0);
 }
 
 int
-mm_answer_gss_error(int socket, Buffer *m) {
-        OM_uint32 major,minor;
-        char *msg;
+mm_answer_gss_localname(int socket, Buffer *m) {
+       char *name;
 
-       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);
+       ssh_gssapi_localname(&name);
 
-       mm_request_send(socket,MONITOR_ANS_GSSERR,m);
+        buffer_clear(m);
+       if (name) {
+           buffer_put_cstring(m, name);
+           debug3("%s: sending result %s", __func__, name);
+           xfree(name);
+       } else {
+           buffer_put_cstring(m, "");
+           debug3("%s: sending result \"\"", __func__);
+       }
+
+        mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m);
 
-       xfree(msg);
-       
         return(0);
 }
-
 #endif /* GSSAPI */
 
 #ifdef GSI
index 2b722fa4f51be4cf49c9b8222603151b518a1db8..06ade4f269bf58ba39ce62fb1c4a46edfd4a88bc 100644 (file)
@@ -43,8 +43,8 @@ enum monitor_reqtype {
        MONITOR_REQ_GSSSETUP,MONITOR_ANS_GSSSETUP,
        MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP,
        MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN,
-       MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS,
        MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS,
        MONITOR_REQ_GSSLOCALNAME,MONITOR_ANS_GSSLOCALNAME,
        MONITOR_REQ_GSIGRIDMAP,MONITOR_ANS_GSIGRIDMAP,
        MONITOR_REQ_GSSERR,MONITOR_ANS_GSSERR,
index b1552fd7ef0f47dc41309f0be83000bf1c4367f4..b68003287135e495c0ee2f501e18f3de11611f59 100644 (file)
@@ -1084,30 +1084,6 @@ mm_ssh_gssapi_userok(char *user) {
         return(authenticated);
 }
 
-int
-mm_ssh_gssapi_localname(char **lname)
-{
-        Buffer m;
-
-       buffer_init(&m);
-
-        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m);
-
-        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME,
-                                  &m);
-
-       *lname = buffer_get_string(&m, NULL);
-
-        buffer_free(&m);
-       if (lname[0] == '\0') {
-           debug3("%s: gssapi identity mapping failed", __func__);
-       } else {
-           debug3("%s: gssapi identity mapped to %s", __func__, *lname);
-       }
-       
-        return(0);
-}
-
 OM_uint32
 mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) {
         Buffer m;
@@ -1150,35 +1126,58 @@ mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) {
        
        return(errstr);
 }      
-       
+
 OM_uint32
 mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set)
 {
         Buffer m;
-       OM_uint32 major, lmajor, lminor;
-       int i=0, count;
-
+       OM_uint32 major,minor;
+       int count;
+       gss_OID_desc oid;
        buffer_init(&m);
 
        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m);
-
         mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS,
                                  &m);
         major=buffer_get_int(&m);
-       lmajor=gss_create_empty_oid_set(&lminor, mech_set);
        count=buffer_get_int(&m);
-       for (i=0; i < count; i++) {
-           gss_OID_desc member_oid;
+       
+        gss_create_empty_oid_set(&minor,mech_set);
+       while(count-->0) {
            u_int length;
-           member_oid.elements=buffer_get_string(&m, &length);
-           member_oid.length=length;
-           lmajor=gss_add_oid_set_member(&lminor, &member_oid, mech_set);
+           oid.elements=buffer_get_string(&m,&length);
+           oid.length=length;
+           gss_add_oid_set_member(&minor,&oid,mech_set);
        }
 
        buffer_free(&m);
        
         return(major);
 }
+
+int
+mm_ssh_gssapi_localname(char **lname)
+{
+        Buffer m;
+
+       buffer_init(&m);
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m);
+
+        debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME,
+                                  &m);
+
+       *lname = buffer_get_string(&m, NULL);
+
+        buffer_free(&m);
+       if (lname[0] == '\0') {
+           debug3("%s: gssapi identity mapping failed", __func__);
+       } else {
+           debug3("%s: gssapi identity mapped to %s", __func__, *lname);
+       }
+       
+        return(0);
+}      
 #endif /* GSSAPI */
 
 #ifdef GSI
index f265f3400ac9dbdb20323494b2e700c9393af0b1..91e94d3549081a265274f86b1885f915f0eeed62 100644 (file)
@@ -71,6 +71,7 @@ int mm_ssh_gssapi_localname(char **user);
 OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status,
                                gss_OID_set *mech_set);
 char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+
 #endif
 
 #ifdef GSI
index 71b3819af72fa5ef01c21648fb06f865540a6af2..bc0bf6d3a2acaedf28785810082634044008654f 100644 (file)
@@ -56,6 +56,7 @@
 #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN                 61
 #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE     63    
 #define SSH2_MSG_USERAUTH_GSSAPI_ERROR                 64  
+#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK                        65
 
 #define KEX_GSS_SHA1                                   "gss-group1-sha1-"
 
@@ -130,9 +131,9 @@ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx,gss_OID oid);
 int ssh_gssapi_check_mechanism(gss_OID oid, char *host);
 
 /* In the server */
-gss_OID ssh_gssapi_server_id_kex(Gssctxt *ctx, char *name);
+gss_OID ssh_gssapi_server_id_kex(char *name);
 int ssh_gssapi_userok(char *name);
-int ssh_gssapi_localname(char **user);
+int ssh_gssapi_localname(char **name);
 void ssh_gssapi_server(Kex *kex, Buffer *client_kexinit, 
                       Buffer *server_kexinit);
 
index 7b45c17367662155e177c33da8d3234c52f2be34..b5d1ba1010425a62bbe9054558ae7335a322d5ad 100644 (file)
@@ -230,10 +230,11 @@ 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_response(int type, u_int32_t, void *);
+void   input_gssapi_token(int type, u_int32_t, void *);
+void   input_gssapi_hash(int type, u_int32_t, void *);
 void   input_gssapi_error(int, u_int32_t, void *);
+void   input_gssapi_errtok(int, u_int32_t, void *);
 #endif
 
 void   userauth(Authctxt *, char *);
@@ -511,16 +512,16 @@ userauth_gssapi(Authctxt *authctxt)
        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. */
+        * 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.
-       */
+        * bother trying to get credentials - as the standard fallback will
+        * deal with that kind of failure.
+        */
 
        if (supported==NULL) gss_indicate_mechs(&min, &supported);
        
@@ -530,12 +531,12 @@ userauth_gssapi(Authctxt *authctxt)
                ssh_gssapi_set_oid(gssctxt,&supported->elements[mech]);
 
                /* The DER encoding below only works for lengths<128,
-               * so check this here 
-               */
+                * so check this here 
+                */
                if (supported->elements[mech].length<128 &&
                    !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
                                                      authctxt->host))) {
-                       ok = 1; /* Mechanism works */
+                       ok = 1; /* Mechanism works */
                } else {
                        mech++;
                }
@@ -553,8 +554,8 @@ userauth_gssapi(Authctxt *authctxt)
        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 */
+        * 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);
@@ -572,6 +573,7 @@ userauth_gssapi(Authctxt *authctxt)
         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);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,&input_gssapi_errtok);
        
        mech++; /* Move along to next candidate */
 
@@ -619,6 +621,12 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
                                     GSS_C_NO_BUFFER, &send_tok, 
                                     NULL);
        if (GSS_ERROR(status)) {
+               if (send_tok.length>0) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+                       packet_put_string(send_tok.value,send_tok.length);
+                       packet_send();
+                       packet_write_wait();
+               }
                /* Start again with next method on list */
                debug("Trying to start again");
                clear_auth_state(authctxt);
@@ -656,6 +664,12 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
        packet_check_eom();
        
        if (GSS_ERROR(status)) {
+               if (send_tok.length>0) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+                       packet_put_string(send_tok.value,send_tok.length);
+                       packet_send();
+                       packet_write_wait();
+               }
                /* Start again with the next method in the list */
                clear_auth_state(authctxt);
                userauth(authctxt,NULL);
@@ -677,6 +691,35 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
        }
 }
 
+void
+input_gssapi_errtok(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);
+
+       /* Stick it into GSSAPI and see what it says */
+       status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+                                  &recv_tok, &send_tok, NULL);
+
+       packet_check_eom();
+       
+       /* We can't send a packet to the server */
+
+       /* The draft says that we should wait for the server to fail 
+        * before starting the next authentication. So, we clear the
+        * state, but don't do anything else */
+       clear_auth_state(authctxt);
+       return;
+}
+
 void
 input_gssapi_error(int type, u_int32_t plen, void *ctxt)
 {
This page took 0.083484 seconds and 5 git commands to generate.