]> andersk Git - gssapi-openssh.git/commitdiff
openssh-3.6.1p1-gssapi-20030416.diff from Simon OPENSSH_3_6_1P1_SIMON OPENSSH_3_6_1P1_SIMON_20030417
authorjbasney <jbasney>
Thu, 17 Apr 2003 20:25:21 +0000 (20:25 +0000)
committerjbasney <jbasney>
Thu, 17 Apr 2003 20:25:21 +0000 (20:25 +0000)
15 files changed:
openssh/auth2-gss.c
openssh/gss-genr.c
openssh/gss-serv-gsi.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/session.c
openssh/session.h
openssh/ssh-gss.h
openssh/sshconnect2.c
openssh/sshd.c

index ac1bc8c68df0b4c9230380064f485c21245eed38..bba5c10339b7a805e128d5ee10fd7782592b0599 100644 (file)
@@ -50,6 +50,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
@@ -91,22 +92,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) {
@@ -125,11 +119,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);
                
         packet_send();
         packet_write_wait();
@@ -137,6 +128,8 @@ userauth_gssapi(Authctxt *authctxt)
 
         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;
@@ -157,32 +150,62 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
         recv_tok.value=packet_get_string(&recv_tok.length);
         
         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 */
-                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) {
+                       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(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
                 userauth_finish(authctxt, 0, "gssapi");
+        } else {
+                       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 (maj_status == GSS_S_COMPLETE) {
+                       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
+                       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(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
-                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(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.
@@ -203,14 +226,15 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
         gssctxt=authctxt->methoddata;
         
        /* We don't need to check the status, because the stored credentials
-       * which userok uses are only populated once the context init step
-       * has returned complete.
-       */
+        * which userok uses are only populated once the context init step
+        * has returned complete.
+        */
 
         authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
 
         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");
 }
index 25cab8799031bc0ed1026e15d84c59e35c0be9e2..6090717340187d829d8e40002bce5f8ee3041867 100644 (file)
@@ -81,10 +81,10 @@ ssh_gssapi_client_mechanisms(char *host) {
        gss_indicate_mechs(&min_status,&supported);
        if (datafellows & SSH_BUG_GSSAPI_BER) {
                gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
-                                       *(supported->count+1));
+                                       *((supported->count*2)+1));
        } else {
                gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
-                                       *((supported->count*2)+1));
+                                       *(supported->count*2+1));
        }
        
        buffer_init(&buf);
@@ -98,10 +98,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;
@@ -142,8 +142,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 */
@@ -372,11 +372,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 */
        
        hostinfo = gethostbyname(xhost);
        
@@ -430,7 +430,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 d8714e3e8b0621bfa21442e061736958821a9d96..a1dc646de37ac38b592aae6de3b5e616379b717b 100644 (file)
@@ -78,20 +78,20 @@ ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client)
                char *creds_env = NULL;
 
                /*
-               * This is the current hack with the GSI gssapi library to
-               * export credentials to disk.
-               */
+                * This is the current hack with the GSI gssapi library to
+                * export credentials to disk.
+                */
 
                debug("Exporting delegated credentials");
                
                minor_status = 0xdee0;  /* Magic value */
                major_status =
                        gss_inquire_cred(&minor_status,
-                                       client->creds,
-                                       (gss_name_t *) &creds_env,
-                                       NULL,
-                                       NULL,
-                                       NULL);
+                                        client->creds,
+                                        (gss_name_t *) &creds_env,
+                                        NULL,
+                                        NULL,
+                                        NULL);
 
                if ((major_status == GSS_S_COMPLETE) &&
                    (minor_status == 0xdee1) &&
@@ -100,12 +100,12 @@ ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client)
                        char            *value;
                                
                        /*
-                       * String is of the form:
-                       * X509_USER_DELEG_PROXY=filename
-                       * so we parse out the filename
-                       * and then set X509_USER_PROXY
-                       * to point at it.
-                       */
+                        * String is of the form:
+                        * X509_USER_DELEG_PROXY=filename
+                        * so we parse out the filename
+                        * and then set X509_USER_PROXY
+                        * to point at it.
+                        */
                        value = strchr(creds_env, '=');
                        
                        if (value != NULL)
@@ -115,7 +115,7 @@ ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client)
 #ifdef USE_PAM
                                do_pam_putenv("X509_USER_PROXY",value);
 #endif
-                               client->store.filename=NULL;
+                               client->store.filename=NULL;
                                client->store.envvar="X509_USER_PROXY";
                                client->store.envval=strdup(value);
 
index aa86a459ca2dd2232333f54421d847d9a8419b0c..95c35f58bbd0e7e6775463638ce36f6c407624c9 100644 (file)
@@ -89,7 +89,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;
@@ -142,6 +143,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;
@@ -149,7 +151,7 @@ void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
        gss_OID_set supported;
        
        gss_create_empty_oid_set(&min_status,oidset);
-       gss_indicate_mechs(&min_status, &supported);
+       PRIVSEP(gss_indicate_mechs(&min_status, &supported));
 
        while (supported_mechs[i]->name!=NULL) {
                if ((maj_status=gss_test_oid_set_member(&min_status,
@@ -170,6 +172,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;
@@ -183,11 +187,11 @@ ssh_gssapi_get_ctype(Gssctxt *ctxt) {
        return ((supported_mechs[i]->name!=NULL)?supported_mechs[i]: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) {
@@ -197,23 +201,22 @@ 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);
-
   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) 
 {
@@ -242,13 +245,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))) &&
@@ -266,6 +269,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) {
@@ -277,14 +281,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)
 {
@@ -295,6 +300,7 @@ ssh_gssapi_cleanup_creds(void *ignored)
        }
 }
 
+/* As user */
 void 
 ssh_gssapi_storecreds()
 {
@@ -310,10 +316,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) 
 {
@@ -328,6 +332,7 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep)
        }
 }
 
+/* Priviledged */
 int
 ssh_gssapi_userok(char *user)
 {
@@ -344,6 +349,7 @@ ssh_gssapi_userok(char *user)
        return(0);
 }
 
+/* Priviledged */
 int
 ssh_gssapi_localname(char **user)
 {
index 723094460fd0d04b49ceac9a8c95d42960b739b7..d2445808bbf13b154947303a1ccedb80dcd424f5 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
@@ -81,7 +81,7 @@ kexgss_client(Kex *kex)
        }
                
        token_ptr = GSS_C_NO_BUFFER;
-                       
+                        
        do {
                debug("Calling gss_init_sec_context");
                
@@ -91,8 +91,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)
@@ -111,7 +117,7 @@ kexgss_client(Kex *kex)
                }
                
                /* If we have data to send, then the last message that we
-               * received cannot have been a 'complete'. */
+                * received cannot have been a 'complete'. */
                if (send_tok.length !=0) {
                        if (first) {
                                packet_start(SSH2_MSG_KEXGSS_INIT);
@@ -129,7 +135,7 @@ kexgss_client(Kex *kex)
 
                        
                        /* If we've sent them data, they'd better be polite
-                       * and reply. */
+                        * and reply. */
                
                        type = packet_read();
                        switch (type) {
@@ -168,22 +174,26 @@ 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 
-       * server, which will have set dh_server_pub and msg_tok */
-       
+        * server, which will have set dh_server_pub and msg_tok */
+        
        if (type!=SSH2_MSG_KEXGSS_COMPLETE)
           fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
-                       
+                       
        /* Check f in range [1, p-1] */
         if (!dh_pub_is_valid(dh, dh_server_pub))
                         packet_disconnect("bad server public DH value");
index 5044540cca9fce97e7fe755398ce1268a6cf9052..6f6cb3483f0cbddf87c5432110042bac63a346b1 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;
@@ -67,7 +67,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) {
           fatal("Unknown gssapi mechanism");
        }
@@ -97,8 +97,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)
-                               fatal("Received KEXGSS_CONTINUE without initialising");
                        recv_tok.value=packet_get_string(&recv_tok.length);
                        break;
                default:
@@ -107,12 +105,18 @@ 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);
                
-               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);
@@ -124,6 +128,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();
+               }       
                fatal("accept_ctx died");
        }
        
@@ -197,7 +207,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 32bc42436c45ac5151bcbfe62009b7e7bbd09428..9c6b1975a9f2ed8ff488ffde2653033662f766be 100644 (file)
@@ -138,6 +138,8 @@ 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 *);
+int mm_answer_gss_indicate_mechs(int, Buffer *);
+int mm_answer_gss_localname(int, Buffer *);
 #endif
 
 static Authctxt *authctxt;
@@ -189,8 +191,13 @@ 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_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {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},
+/* Turn this off until we use it */
+#if 0
+    {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
+#endif
 #endif
     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
     {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
@@ -203,6 +210,7 @@ struct mon_table mon_dispatch_postauth20[] = {
     {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},
+    {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs},
 #endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
@@ -296,9 +304,8 @@ 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_GSSERR, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1);
 #endif
        } else {
                mon_dispatch = mon_dispatch_proto15;
@@ -354,6 +361,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);
@@ -1703,6 +1717,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);
 }
 
@@ -1724,8 +1741,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;
@@ -1796,5 +1819,47 @@ mm_answer_gss_error(int socket, Buffer *m) {
         return(0);
 }
 
+int
+mm_answer_gss_indicate_mechs(int socket, Buffer *m) {
+        OM_uint32 major,minor;
+       gss_OID_set mech_set;
+       int i;
+
+       major=gss_indicate_mechs(&minor, &mech_set);
 
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_int(m, mech_set->count);
+       for (i=0; i < mech_set->count; i++) {
+           buffer_put_string(m, mech_set->elements[i].elements,
+                             mech_set->elements[i].length);
+       }
+
+       gss_release_oid_set(&minor,&mech_set);
+       
+       mm_request_send(socket,MONITOR_ANS_GSSMECHS,m);
+
+       return(0);
+}
+
+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);
+}
 #endif /* GSSAPI */
index 1bdddfc36126ba3d11529542774e1e7aa313776d..086bab684e267cc9d83339b7237ac99be0155e49 100644 (file)
@@ -44,6 +44,8 @@ enum monitor_reqtype {
        MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP,
        MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN,
        MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS,
+       MONITOR_REQ_GSSLOCALNAME,MONITOR_ANS_GSSLOCALNAME,
        MONITOR_REQ_GSSERR,MONITOR_ANS_GSSERR,
 #endif
        MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
index a0c4d2a2f77f0216e36e01b1e51441b34ec0c1c6..e23f72d8b7386d2caac8987dfb4bdb07df9bc662 100644 (file)
@@ -1126,5 +1126,54 @@ 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,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);
+       count=buffer_get_int(&m);
+       
+        gss_create_empty_oid_set(&minor,mech_set);
+       while(count-->0) {
+           oid.elements=buffer_get_string(&m,&oid.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 */
index 85173e194cd6c49ced695990cf864cc0a8abd3d2..ffd2f2884b5200bbef58f042a3638aa53d4d0634 100644 (file)
@@ -68,6 +68,7 @@ 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);
index 7bab8900f1d01556a8d531567d52c6f1fec973b5..e85bc9ee858738c9597db751f4cf7d439356ffb7 100644 (file)
@@ -985,8 +985,8 @@ do_setup_env(Session *s, const char *shell)
 
 #ifdef GSSAPI
        /* Allow any GSSAPI methods that we've used to alter 
-       * the childs environment as they see fit
-       */
+        * the childs environment as they see fit
+        */
        ssh_gssapi_do_child(&env,&envsize);
 #endif
 
index 012f0ff37439f7afa3b91c19c6f5ce2f49322e74..7fc3653cde92e42e8141ab4bcd25864ae0c22809 100644 (file)
@@ -69,6 +69,6 @@ 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,
+void    child_set_env(char ***envp, u_int *envsizep, const char *name,
                       const char *value);
 #endif
index 1d2ec3696b54fd0bf7c999b99d9f9f05cbd0440c..22602328eb3d31138951f9dbbfa426e22f7da8c5 100644 (file)
@@ -53,6 +53,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-"
 
@@ -126,8 +127,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 **name);
 void ssh_gssapi_server(Kex *kex, Buffer *client_kexinit, 
                       Buffer *server_kexinit);
 
index cf193882742f5f4ff69f30068955af289bd715c3..39cffd9c099f3864ee979b47e37b69dc09857399 100644 (file)
@@ -91,7 +91,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
 
 #ifdef GSSAPI
        /* Add the GSSAPI mechanisms currently supported on this client to
-       * the key exchange algorithm proposal */
+        * the key exchange algorithm proposal */
        orig = myproposal[PROPOSAL_KEX_ALGS];
        gss = ssh_gssapi_client_mechanisms(host);
        if (gss) {
@@ -223,10 +223,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 *);
@@ -504,16 +505,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);
        
@@ -523,12 +524,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++;
                }
@@ -546,8 +547,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);
@@ -565,6 +566,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 */
 
@@ -612,6 +614,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);
@@ -647,6 +655,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);
@@ -668,6 +682,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)
 {
index c595b28127afde560cfb2a3986f75b93818724be..2e0fee561ac2cea2c202f9e192f3a2ca91b0d607 100644 (file)
@@ -1831,7 +1831,7 @@ do_ssh2_kex(void)
                orig = myproposal[PROPOSAL_KEX_ALGS];
 
        /* If we don't have a host key, then all of the algorithms
-       * currently in myproposal are useless */
+        * currently in myproposal are useless */
        if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])==0)
                orig= NULL;
                
This page took 0.096367 seconds and 5 git commands to generate.