gsscon: callback for client name validation
authorSam Hartman <hartmans@debian.org>
Mon, 8 Jul 2013 19:08:29 +0000 (15:08 -0400)
committerSam Hartman <hartmans@debian.org>
Mon, 8 Jul 2013 19:13:38 +0000 (15:13 -0400)
gsscon_passive_authenticate now takes a callback for client authentication.

gsscon/gsscon_passive.c
gsscon/test/gsscon_server.c
include/gsscon.h

index 96d1417..87506fc 100755 (executable)
 const char *gServiceName = NULL;
 
 int gsscon_passive_authenticate (int           inSocket, 
-                         gss_ctx_id_t *outGSSContext)
+                                gss_ctx_id_t *outGSSContext,
+                                client_cb_fn clientCb,
+                                void *clientCbData)
 {
     int err = 0;
     OM_uint32 majorStatus;
     OM_uint32 minorStatus = 0;
     gss_ctx_id_t gssContext = GSS_C_NO_CONTEXT;
+    gss_name_t clientName = GSS_C_NO_NAME;
+    gss_buffer_desc clientDisplayName = {0, NULL};
     
     char *inputTokenBuffer = NULL;
     size_t inputTokenBufferLength = 0;
     gss_buffer_desc inputToken;  /* buffer received from the server */
     
+
     if (inSocket <  0 ) { err = EINVAL; }
     if (!outGSSContext) { err = EINVAL; }
     
@@ -107,28 +112,16 @@ int gsscon_passive_authenticate (int           inSocket,
             /*
              * accept_sec_context does the actual work of taking the client's 
              * request and generating an appropriate reply.  Note that we pass 
-             * GSS_C_NO_CREDENTIAL for the service principal.  This causes the 
-             * server to accept any service principal in the server's keytab, 
-             * which enables you to support multihomed hosts by having one key 
-             * in the keytab for each host identity the server responds on.  
-             *
-             * However, since we may have more keys in the keytab than we want 
-             * the server to actually use, we will need to check which service 
-             * principal the client used after authentication succeeds.  See 
-             * ServicePrincipalIsValidForService() for where you would put these 
-             * checks.  We don't check here since if we stopped responding in the 
-             * middle of the authentication negotiation, the client would get an 
-             * EOF, and the user wouldn't know what went wrong.
-             */
-            
+             * GSS_C_NO_CREDENTIAL for the service principal.
+            */
            // printf ("Calling gss_accept_sec_context...\n");
             majorStatus = gss_accept_sec_context (&minorStatus, 
                                                   &gssContext, 
                                                   GSS_C_NO_CREDENTIAL, 
                                                   &inputToken, 
                                                   GSS_C_NO_CHANNEL_BINDINGS, 
-                                                  NULL /* client_name */, 
-                                                  NULL /* actual_mech_type */, 
+                                                  &clientName,
+                                                  NULL /* actual_mech_type */,
                                                   &outputToken, 
                                                   NULL /* req_flags */, 
                                                   NULL /* time_rec */, 
@@ -148,7 +141,17 @@ int gsscon_passive_authenticate (int           inSocket,
             err = minorStatus ? minorStatus : majorStatus; 
         }            
     }
-    
+
+    if (!err) {
+      majorStatus = gss_display_name(&minorStatus, clientName, &clientDisplayName, NULL);
+      if (GSS_ERROR(majorStatus)) {
+       gsscon_print_gss_errors("gss_display_name", majorStatus, minorStatus);
+       err = EINVAL;
+      }
+      if (!err)
+       err = clientCb(clientName, &clientDisplayName, clientCbData);
+    }
+
     if (!err) { 
         *outGSSContext = gssContext;
         gssContext = NULL;
@@ -159,6 +162,10 @@ int gsscon_passive_authenticate (int           inSocket,
     if (inputTokenBuffer) { free (inputTokenBuffer); }
     if (gssContext != GSS_C_NO_CONTEXT) { 
         gss_delete_sec_context (&minorStatus, &gssContext, GSS_C_NO_BUFFER); }
+if (clientName != GSS_C_NO_NAME)
+  gss_release_name(&minorStatus, &clientName);
+if (clientDisplayName.value != NULL)
+  gss_release_buffer(&minorStatus, &clientDisplayName);
         
     return err;
 }
index 63b460a..d7d3847 100644 (file)
  */
 
 #include <gsscon.h>
+#include <assert.h>
 
+static int cb_print_names(gss_name_t clientName,
+                         gss_buffer_t displayName,
+                         void *data)
+{
+  assert(clientName != NULL);
+  assert(data == NULL);
+  printf("Gss name: %-*s\n",
+        displayName->length, displayName->value);
+  return 0;
+}
+
+  
 /* --------------------------------------------------------------------------- */
 
 static int SetupListeningSocket (int  inPort, 
@@ -153,7 +166,8 @@ int main (int argc, const char *argv[])
         }
         
         printf ("Accepting new connection...\n");
-        connectionErr = gsscon_passive_authenticate (connectionFD, &gssContext);
+        connectionErr = gsscon_passive_authenticate (connectionFD, &gssContext,
+                                                    cb_print_names, NULL);
         
         if (!connectionErr) {
             connectionErr = gsscon_authorize (gssContext, 
index f0bfec3..35ff039 100644 (file)
 #define kDefaultPort 2000
 extern const char *gServiceName;
 
+typedef int (*client_cb_fn)(
+                           gss_name_t client_name, gss_buffer_t client_display_name,
+                           void *);
+
 int gsscon_read_token (int      inSocket, 
                char   **outTokenValue, 
                size_t  *outTokenLength);
@@ -105,7 +109,9 @@ int gsscon_connect (const char *inHost,
                    gss_ctx_id_t *outGSSContext);
 
 int gsscon_passive_authenticate (int           inSocket, 
-                                gss_ctx_id_t *outGSSContext);
+                                gss_ctx_id_t *outGSSContext,
+                                client_cb_fn client_cb,
+                                void *client_cb_data);
 
 int gsscon_authorize (gss_ctx_id_t  inContext, 
                       int          *outAuthorized,