]> andersk Git - gssapi-openssh.git/blobdiff - openssh/gss-serv.c
revision: solve the compilation problem when both GSI and Kerberos are supported...
[gssapi-openssh.git] / openssh / gss-serv.c
index b29df32fa64ef9581631f43abf5b107cbc690a3a..ceef7dc7054cdff1c958b1bf9d93db444441c07c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001,2002 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,7 +45,6 @@
 #include "servconf.h"
 #include "compat.h"
 #include "misc.h"
-#include "monitor_wrap.h"
 
 #include "ssh-gss.h"
 
@@ -53,6 +52,9 @@ extern ServerOptions options;
 extern u_char *session_id2;
 extern int session_id2_len;
 
+void    userauth_reply(Authctxt *authctxt, int authenticated);
+static void gssapi_unsetenv(const char *var);
+
 typedef struct ssh_gssapi_cred_cache {
        char *filename;
        char *envvar;
@@ -61,6 +63,7 @@ typedef struct ssh_gssapi_cred_cache {
 } ssh_gssapi_cred_cache;
 
 static struct ssh_gssapi_cred_cache gssapi_cred_store = {NULL,NULL,NULL};
+unsigned char ssh1_key_digest[16]; /* used for ssh1 gssapi */
 
 /*
  * Environment variables pointing to delegated credentials
@@ -71,8 +74,6 @@ static char *delegation_env[] = {
   NULL
 };
 
-static void gssapi_unsetenv(const char *var);
-
 #ifdef KRB5
 
 #ifdef HEIMDAL
@@ -133,23 +134,6 @@ ssh_gssapi_krb5_userok(char *name) {
        krb5_free_principal(krb_context, princ);
        return retval;
 }
-
-int
-ssh_gssapi_krb5_localname(char **user)
-{
-    krb5_principal princ;
-
-    if (krb5_parse_name(krb_context, gssapi_client_name.value, &princ)) {
-       return(0);
-    }
-    *user = (char *)xmalloc(256);
-    if (krb5_aname_to_localname(krb_context, princ, 256, *user)) {
-       xfree(*user);
-       *user = NULL;
-       return(0);
-    }
-    return(1);
-}
        
 /* Make sure that this is called _after_ we've setuid to the user */
 
@@ -265,7 +249,7 @@ ssh_gssapi_krb5_storecreds() {
 #endif /* KRB5 */
 
 #ifdef GSI
-#include <globus_gss_assist.h>
+#include "globus_gss_assist_gsi.h"
 
 /*
  * Check if this user is OK to login under GSI. User has been authenticated
@@ -289,15 +273,6 @@ ssh_gssapi_gsi_userok(char *name)
     return authorized;
 }
 
-/*
- * Return the local username associated with the GSI credentials.
- */
-int
-ssh_gssapi_gsi_localname(char **user)
-{
-    return(globus_gss_assist_gridmap(gssapi_client_name.value, user) == 0);
-}
-
 /*
  * Handle setting up child environment for GSI.
  *
@@ -388,16 +363,16 @@ void
 ssh_gssapi_storecreds()
 {
        switch (gssapi_client_type) {
-#ifdef KRB5
-       case GSS_KERBEROS:
-               ssh_gssapi_krb5_storecreds();
-               break;
-#endif
 #ifdef GSI
        case GSS_GSI:
                ssh_gssapi_gsi_storecreds();
                break;
 #endif /* GSI */
+#ifdef KRB5
+       case GSS_KERBEROS:
+               ssh_gssapi_krb5_storecreds();
+               break;
+#endif
        case GSS_LAST_ENTRY:
                /* GSSAPI not used in this authentication */
                debug("No GSSAPI credentials stored");
@@ -476,32 +451,225 @@ ssh_gssapi_userok(char *user)
 }
 
 int
-ssh_gssapi_localname(char **user)
+userauth_external(Authctxt *authctxt)
 {
-       *user = NULL;
-       if (gssapi_client_name.length==0 || 
-           gssapi_client_name.value==NULL) {
-               debug("No suitable client data");
-               return(0);;
+       packet_check_eom();
+
+       return(ssh_gssapi_userok(authctxt->user));
+}
+
+void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
+void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
+
+/* We only support those mechanisms that we know about (ie ones that we know
+ * how to check local user kuserok and the like
+ */
+int
+userauth_gssapi(Authctxt *authctxt)
+{
+       gss_OID_desc    oid= {0,NULL};
+       Gssctxt         *ctxt;
+       int             mechs;
+       gss_OID_set     supported;
+       int             present;
+       OM_uint32       ms;
+       u_int           len;
+       
+       if (!authctxt->valid || authctxt->user == NULL)
+               return 0;
+               
+       if (datafellows & SSH_OLD_GSSAPI) {
+               debug("Early drafts of GSSAPI userauth not supported");
+               return 0;
        }
-       switch (gssapi_client_type) {
-#ifdef KRB5
-       case GSS_KERBEROS:
-               return(ssh_gssapi_krb5_localname(user));
-               break; /* Not reached */
-#endif
-#ifdef GSI
-       case GSS_GSI:
-               return(ssh_gssapi_gsi_localname(user));
-               break; /* Not reached */
-#endif /* GSI */
-       case GSS_LAST_ENTRY:
-               debug("Client not GSSAPI");
-               break;
-       default:
-               debug("Unknown client authentication type");
+       
+       mechs=packet_get_int();
+       if (mechs==0) {
+               debug("Mechanism negotiation is not supported");
+               return 0;
        }
-       return(0);
+
+       ssh_gssapi_supported_oids(&supported);
+       do {
+               if (oid.elements)
+                       xfree(oid.elements);
+               oid.elements = packet_get_string(&len);
+               oid.length = len;
+               gss_test_oid_set_member(&ms, &oid, supported, &present);
+               mechs--;
+       } while (mechs>0 && !present);
+       
+       if (!present) {
+               xfree(oid.elements);
+               return(0);
+       }
+       
+       ctxt=xmalloc(sizeof(Gssctxt));
+       authctxt->methoddata=(void *)ctxt;
+       
+       ssh_gssapi_build_ctx(ctxt);
+       ssh_gssapi_set_oid(ctxt,&oid);
+
+       if (ssh_gssapi_acquire_cred(ctxt))
+               return 0;
+
+       /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */
+
+       if (!compat20)
+       packet_start(SSH_SMSG_AUTH_GSSAPI_RESPONSE);
+       else
+       packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
+       packet_put_string(oid.elements,oid.length);
+       packet_send();
+       packet_write_wait();
+       xfree(oid.elements);
+               
+       if (!compat20)
+       dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN,
+                               &input_gssapi_token);
+       else
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, 
+                    &input_gssapi_token);
+       authctxt->postponed = 1;
+       
+       return 0;
+}
+
+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 maj_status, min_status;
+       
+       if (authctxt == NULL || authctxt->methoddata == NULL)
+               fatal("No authentication or GSSAPI context");
+               
+       gssctxt=authctxt->methoddata;
+
+       recv_tok.value=packet_get_string(&recv_tok.length);
+       
+       maj_status=ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok, NULL);
+       packet_check_eom();
+       
+       if (GSS_ERROR(maj_status)) {
+               /* Failure <sniff> */
+               ssh_gssapi_send_error(maj_status,min_status);
+               authctxt->postponed = 0;
+               dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
+               dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+               userauth_finish(authctxt, 0, "gssapi");
+       }
+                       
+       if (send_tok.length != 0) {
+               /* Send a packet back to the client */
+               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 (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);
+       }
+}
+
+/* This is called when the client thinks we've completed authentication.
+ * It should only be enabled in the dispatch handler by the function above,
+ * which only enables it once the GSSAPI exchange is complete.
+ */
+void
+input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       int authenticated;
+
+       if(strcmp(authctxt->user,"") == 0) {
+               char *user;
+               char *gridmapped_name = NULL;
+               struct passwd *pw = NULL;
+               if(globus_gss_assist_gridmap(gssapi_client_name.value,
+                           &gridmapped_name) == 0) {
+                               user = gridmapped_name;
+                               debug("I gridmapped and got %s", user);
+                               pw = getpwnam(user);
+                               if (pw && allowed_user(pw)) {
+                               authctxt->user = user;
+                               authctxt->pw = pwcopy(pw);
+                               authctxt->valid = 1;
+                               }
+               }
+       }
+
+       
+       if (authctxt == NULL || authctxt->methoddata == NULL)
+               fatal("No authentication or GSSAPI context");
+               
+       gssctxt=authctxt->methoddata;
+
+       /* This should never happen, but better safe than sorry. */
+       if (gssctxt->status != GSS_S_COMPLETE) {
+               packet_disconnect("Context negotiation is not complete");
+       }
+
+       if (ssh_gssapi_getclient(gssctxt,&gssapi_client_type,
+                                &gssapi_client_name,
+                                &gssapi_client_creds)) {
+               fatal("Couldn't convert client name");
+       }
+                                               
+        authenticated = ssh_gssapi_userok(authctxt->user);
+
+       /* ssh1 needs to exchange the hash of the keys */
+       if (!compat20) {
+               if (authenticated) {
+
+                       OM_uint32 maj_status, min_status;
+                       gss_buffer_desc gssbuf,msg_tok;
+
+                       /* ssh1 uses wrap */
+                       gssbuf.value=ssh1_key_digest;
+                       gssbuf.length=sizeof(ssh1_key_digest);
+                       if ((maj_status=gss_wrap(&min_status,
+                                       gssctxt->context,
+                                       0,
+                                       GSS_C_QOP_DEFAULT,
+                                       &gssbuf,
+                                       NULL,
+                                       &msg_tok))) {
+                               ssh_gssapi_error(maj_status,min_status);
+                               fatal("Couldn't wrap keys");
+                       }
+                       packet_start(SSH_SMSG_AUTH_GSSAPI_HASH);
+                       packet_put_string((char *)msg_tok.value,msg_tok.length);
+                       packet_send();
+                       packet_write_wait();
+                       gss_release_buffer(&min_status,&msg_tok);
+               } else {
+                   packet_start(SSH_MSG_AUTH_GSSAPI_ABORT);
+                   packet_send();
+                   packet_write_wait();
+               }
+       }
+
+       authctxt->postponed = 0;
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+       userauth_finish(authctxt, authenticated, "gssapi");
 }
 
 /*
This page took 0.107405 seconds and 4 git commands to generate.