]> arthur.barton.de Git - netatalk.git/commitdiff
-cleanup uams_gss.c
authorbfernhomberg <bfernhomberg>
Tue, 7 Dec 2004 18:41:08 +0000 (18:41 +0000)
committerbfernhomberg <bfernhomberg>
Tue, 7 Dec 2004 18:41:08 +0000 (18:41 +0000)
-build the principal used by uams_gss.so from afpd's configuration, don't use GSS_C_NT_HOSTBASED_SERVICE

etc/afpd/uam.c
etc/uams/uams_gss.c
include/atalk/uam.h

index 2d752531916b95ea31a73dfb09f95f607bf8ceba..f01fda7a04b5e16e62e2bd74b55c0bb6c1f17330 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: uam.c,v 1.24.6.7.2.1 2004-12-07 18:34:15 bfernhomberg Exp $
+ * $Id: uam.c,v 1.24.6.7.2.2 2004-12-07 18:41:08 bfernhomberg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
@@ -499,6 +499,16 @@ AFPObj *obj = private;
         if (len)
             *len = (*buf)?strlen(*buf):0;
        break;
+    case UAM_OPTION_KRB5REALM:
+       *buf = obj->options.k5realm;
+        if (len)
+            *len = (*buf)?strlen(*buf):0;
+       break;
+    case UAM_OPTION_FQDN:
+       *buf = obj->options.fqdn;
+        if (len)
+            *len = (*buf)?strlen(*buf):0;
+       break;
     case UAM_OPTION_MACCHARSET:
         *((int *) option) = obj->options.maccharset;
         *len = sizeof(obj->options.maccharset);
index 05a1cfbe35822a796f508788ad63726008d9c2f3..965975b899acc926a1461c34015c7e39b38c6fec 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * $Id: uams_gss.c,v 1.2.2.4 2004-06-20 15:51:46 bfernhomberg Exp $
+ * $Id: uams_gss.c,v 1.2.2.4.2.1 2004-12-07 18:41:10 bfernhomberg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
  * Copyright (c) 2003 The Reed Institute
+ * Copyright (c) 2004 Bjoern Fernhomberg
  * All Rights Reserved.  See COPYRIGHT.
  */
 
@@ -37,6 +38,7 @@ char *strchr (), *strrchr ();
 #include <atalk/logger.h>
 #include <atalk/afp.h>
 #include <atalk/uam.h>
+#include <atalk/util.h>
 
 /* Kerberos includes */
 
@@ -100,161 +102,342 @@ static void log_status( char *s, OM_uint32 major_status,
 }
 
 
-void log_ctx_flags( OM_uint32 flags )
+static void log_ctx_flags( OM_uint32 flags )
 {
+#ifdef DEBUG1
     if (flags & GSS_C_DELEG_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_DELEG_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_DELEG_FLAG" );
     if (flags & GSS_C_MUTUAL_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_MUTUAL_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_MUTUAL_FLAG" );
     if (flags & GSS_C_REPLAY_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_REPLAY_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_REPLAY_FLAG" );
     if (flags & GSS_C_SEQUENCE_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_SEQUENCE_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_SEQUENCE_FLAG" );
     if (flags & GSS_C_CONF_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_CONF_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_CONF_FLAG" );
     if (flags & GSS_C_INTEG_FLAG)
-        LOG(log_info, logtype_uams, "uams_gss.c :context flag: GSS_C_INTEG_FLAG" );
+        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_INTEG_FLAG" );
+#endif
 }
 
-/* return 0 on success */
-static int do_gss_auth( char *service, char *ibuf, int ticket_len,
-                char *rbuf, int *rbuflen, char *username, int ulen,
-                struct session_info *sinfo ) 
+static void log_principal(gss_name_t server_name)
 {
+#ifdef DEBUG1
     OM_uint32 major_status = 0, minor_status = 0;
-    gss_name_t server_name;
-    gss_cred_id_t server_creds;
-    gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
-    gss_buffer_desc ticket_buffer, authenticator_buff, sesskey_buff, wrap_buff;
-    gss_name_t client_name;
-    OM_uint32  ret_flags;
-    int ret = 0;
-    /* FIXME
-     * princ specifies the principal to be used.
-     * The user specifies it when configuring afpd anyway,
-     * we should be able to detect it.
-     */
+    gss_buffer_desc exported_name;
+
+    /* Only for debugging purposes, check the gssapi internal representation */
+    major_status = gss_export_name(&minor_status, server_name, &exported_name);
+    LOG(log_debug, logtype_uams, "log_principal: exported server name is %s", (char*) exported_name.value);
+    gss_release_buffer( &minor_status, &exported_name );
+#endif
+}
+
+/* get the principal from afpd and import it into server_name */
+static int get_afpd_principal(void *obj, gss_name_t *server_name)
+{
+    OM_uint32 major_status = 0, minor_status = 0;
+    char *realm, *fqdn, *service, *principal, *p;
+    int realmlen=0, fqdnlen=0, servicelen=0;
+    size_t principal_length;
     gss_buffer_desc s_princ_buffer;
 
-    s_princ_buffer.value = service;
-    s_princ_buffer.length = strlen( service ) + 1;
-    
-    /* outline:
-     * gss_import_name (need a way to get this from afpd)
-     * gss_acquire_credential
-     * gss_accept_sec_context
-     * ...
+    /* get all the required information from afpd */
+    if (uam_afpserver_option(obj, UAM_OPTION_KRB5REALM, (void*) &realm, &realmlen) < 0) 
+       return 1;
+    if (uam_afpserver_option(obj, UAM_OPTION_FQDN, (void*) &fqdn, &fqdnlen) < 0) 
+       return 1;
+    if (uam_afpserver_option(obj, UAM_OPTION_KRB5SERVICE, (void *)&service, &servicelen) < 0)
+        return 1;
+
+    /* we need all the info, log error and return if one's missing */
+    if (!service || !servicelen || !fqdn || !fqdnlen || !realm || !realmlen) {
+        LOG(log_error, logtype_uams, 
+            "get_afpd_principal: could not retrieve required information from afpd.");
+        return 1;
+    }
+
+    /* allocate memory to hold the temporary principal string */
+    principal_length = servicelen + 1 + fqdnlen + 1 + realmlen + 1;
+    if ( NULL == (principal = (char*) malloc( principal_length)) ) {
+        LOG(log_error, logtype_uams,
+            "get_afpd_principal: out of memory allocating %u bytes", 
+            principal_length);
+        return 1;
+    }
+
+    /*
+     * Build the principal string.
+     * Format: 'service/fqdn@realm'
+     */
+    strlcpy( principal, service, principal_length);
+    strlcat( principal, "/", principal_length);
+
+    /* 
+     * The fqdn we get from afpd may contain a port.
+     * We need to strip the port from fqdn for principal.
+     */
+    p = strchr(fqdn, ':');
+    if (p)
+       *p = '\0';
+    strlcat( principal, fqdn, principal_length);
+    if (p)
+       *p = ':';
+    strlcat( principal, "@", principal_length);
+    strlcat( principal, realm, principal_length);
+
+    /*
+     * Import our principal into the gssapi internal representation
+     * stored in server_name.
+     */
+    s_princ_buffer.value = principal;
+    s_princ_buffer.length = strlen( principal ) + 1;
+
+    LOG(log_debug, logtype_uams, "get_afpd_principal: importing principal `%s'", principal);
+    major_status = gss_import_name( &minor_status,
+                    &s_princ_buffer,
+                    GSS_C_NO_OID,
+                    server_name );
+
+    /* 
+     * Get rid of malloc'ed memmory.
+     * Don't release the s_princ_buffer, we free principal instead.
      */
-    LOG(log_debug, logtype_uams, "uams_gss.c :do_gss_auth: importing name" );
-    major_status = gss_import_name( &minor_status, 
-                   &s_princ_buffer, 
-                   GSS_C_NT_HOSTBASED_SERVICE,
-                   &server_name );
+    free(principal);
+
     if (major_status != GSS_S_COMPLETE) {
-       log_status( "import_name", major_status, minor_status );
-       ret = 1;
-       goto cleanup_vars;
+        /* Importing our service principal failed, bail out. */
+        log_status( "import_principal", major_status, minor_status );
+        return 1;
     }
-    
-    LOG(log_debug, logtype_uams, 
-       "uams_gss.c :do_gss_auth: acquiring credentials (uid = %d, keytab = %s)",
+    return 0;
+}
+
+
+/* get the username */
+static int get_client_username(char *username, int ulen, gss_name_t *client_name)
+{
+    OM_uint32 major_status = 0, minor_status = 0;
+    gss_buffer_desc client_name_buffer;
+    char *p;
+    int namelen, ret=0;
+
+    /* 
+     * To extract the unix username, use gss_display_name on client_name.
+     * We do rely on gss_display_name returning a zero terminated string.
+     * The username returned contains the realm and possibly an instance.
+     * We only want the username for afpd, so we have to strip those from
+     * the username before copying it to afpd's buffer.
+     */
+
+    major_status = gss_display_name( &minor_status, *client_name,
+                                     &client_name_buffer, (gss_OID *)NULL );
+    if (major_status != GSS_S_COMPLETE) {
+        log_status( "display_name", major_status, minor_status );
+        return 1;
+    }
+
+    LOG(log_debug, logtype_uams, "get_client_username: user is `%s'", client_name_buffer.value);
+
+    /* chop off realm */
+    p = strchr( client_name_buffer.value, '@' );
+    if (p)
+        *p = 0;
+    /* FIXME: chop off instance? */
+    p = strchr( client_name_buffer.value, '/' );
+    if (p)
+        *p = 0;
+
+    /* check if this username fits into afpd's username buffer */
+    namelen = strlen(client_name_buffer.value);
+    if ( namelen >= ulen ) {
+        /* The username is too long for afpd's buffer, bail out */
+        LOG(log_error, logtype_uams,
+            "get_client_username: username `%s' too long", client_name_buffer.value);
+        ret = 1;
+    }
+    else {
+        /* copy stripped username to afpd's buffer */
+        strlcpy(username, client_name_buffer.value, ulen);
+    }
+
+    /* we're done with client_name_buffer, release it */
+    gss_release_buffer(&minor_status, &client_name_buffer );
+
+    return ret;
+}
+
+/* wrap afpd's sessionkey */
+static int wrap_sessionkey(gss_ctx_id_t context, struct session_info *sinfo)
+{
+    OM_uint32 status = 0;
+    int ret=0;
+    gss_buffer_desc sesskey_buff, wrap_buff;
+
+    /* 
+     * gss_wrap afpd's session_key.
+     * This is needed fo OS X 10.3 clients. They request this information
+     * with type 8 (kGetKerberosSessionKey) on FPGetSession.
+     * See AFP 3.1 specs, page 77.
+     */
+
+    sesskey_buff.value = sinfo->sessionkey;
+    sesskey_buff.length = sinfo->sessionkey_len;
+
+    /* gss_wrap the session key with the default mechanism. 
+       Require both confidentiality and integrity services */
+    gss_wrap (&status, context, 1, GSS_C_QOP_DEFAULT, &sesskey_buff, NULL, &wrap_buff);
+
+    if ( status != GSS_S_COMPLETE) {
+        LOG(log_error, logtype_uams, "wrap_sessionkey: failed to gss_wrap sessionkey");
+       log_status( "GSS wrap", 0, status );
+        return 1;
+    }
+
+    /* store the wrapped session key in afpd's session_info struct */
+    if ( NULL == (sinfo->cryptedkey = malloc ( wrap_buff.length )) ) {
+        LOG(log_error, logtype_uams, 
+            "wrap_sessionkey: out of memory tyring to allocate %u bytes", 
+            wrap_buff.length);
+        ret = 1;
+    } else {
+        /* cryptedkey is binary data */
+        memcpy (sinfo->cryptedkey, wrap_buff.value, wrap_buff.length);
+        sinfo->cryptedkey_len = wrap_buff.length;
+    }
+
+    /* we're done with buffer, release */
+    gss_release_buffer( &status, &wrap_buff );
+
+    return ret;
+}
+
+/*-------------*/
+static int acquire_credentials (gss_name_t *server_name, gss_cred_id_t *server_creds)
+{
+    OM_uint32 major_status = 0, minor_status = 0;
+
+    LOG(log_debug, logtype_uams,
+        "acquire credentials: acquiring credentials (uid = %d, keytab = %s)",
         (int)geteuid(), getenv( "KRB5_KTNAME") );
+   /*
+    * Acquire credentials usable for accepting context negotiations.
+    * Credentials are for server_name, have an indefinite lifetime,
+    * have no specific mechanisms, are to be used for accepting context 
+    * negotiations and are to be placed in server_creds. 
+    * We don't care about the mechanisms or about the time for which they are valid.
+    */
+    major_status = gss_acquire_cred( &minor_status, *server_name,
+                        GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT,
+                        server_creds, NULL, NULL );
 
-    major_status = gss_acquire_cred( &minor_status, server_name, 
-                       GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT,
-                       &server_creds, NULL, NULL );    
     if (major_status != GSS_S_COMPLETE) {
-       log_status( "acquire_cred", major_status, minor_status );
-       ret = 1;
-       goto cleanup_vars;
+        log_status( "acquire_cred", major_status, minor_status );
+        return 1;
     }
+   
+    return 0;
+}
+
+/*-------------*/
+static int accept_sec_context (gss_ctx_id_t *context, gss_cred_id_t server_creds, 
+                           gss_buffer_desc *ticket_buffer, gss_name_t *client_name,
+                           gss_buffer_desc *authenticator_buff)
+{
+    OM_uint32 major_status = 0, minor_status = 0, ret_flags;
+
+    /* Initialize autheticator buffer. */
+    authenticator_buff->length = 0;
+    authenticator_buff->value = NULL;
 
-    /* The GSSAPI docs say that this should be done in a big "do" loop,
-     * but Apple's implementation doesn't seem to support this behavior.
+    LOG(log_debug, logtype_uams, "accept_context: accepting context (ticketlen: %u)", 
+        ticket_buffer->length);
+
+    /* 
+     * Try to accept the secondary context using the tocken in ticket_buffer.
+     * We don't care about the mechanisms used, nor for the time. 
+     * We don't act as a proxy either.
+     */
+    major_status = gss_accept_sec_context( &minor_status, context,
+                        server_creds, ticket_buffer, GSS_C_NO_CHANNEL_BINDINGS,
+                        client_name, NULL, authenticator_buff,
+                        &ret_flags, NULL, NULL );
+
+    if (major_status != GSS_S_COMPLETE) {
+        log_status( "accept_sec_context", major_status, minor_status );
+        return 1;
+    }
+    log_ctx_flags( ret_flags );
+    return 0;
+}
+    
+
+/* return 0 on success */
+static int do_gss_auth(void *obj, char *ibuf, int ticket_len,
+                char *rbuf, int *rbuflen, char *username, int ulen,
+                struct session_info *sinfo ) 
+{
+    OM_uint32 status = 0;
+    gss_name_t server_name, client_name;
+    gss_cred_id_t server_creds;
+    gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
+    gss_buffer_desc ticket_buffer, authenticator_buff;
+    int ret = 0;
+
+    /* import our principal name from afpd */
+    if (get_afpd_principal(obj, &server_name) != 0) {
+        return 1;
+    }
+    log_principal(server_name);
+  
+    /* Now we have to acquire our credentials */
+    if ((ret = acquire_credentials (&server_name, &server_creds)))
+       goto cleanup_vars;
+
+    /* 
+     * Try to accept the secondary context, using the ticket/token the 
+     * client sent us. Ticket is stored at current ibuf position. 
+     * Don't try to release ticket_buffer later, it points into ibuf! 
      */
     ticket_buffer.length = ticket_len;
     ticket_buffer.value = ibuf;
-    authenticator_buff.length = 0;
-    authenticator_buff.value = NULL;
-    LOG(log_debug, logtype_uams, "uams_gss.c :do_gss_auth: accepting context (ticketlen: %u)", ticket_buffer.length);
-    major_status = gss_accept_sec_context( &minor_status, &context_handle,
-                       server_creds, &ticket_buffer, GSS_C_NO_CHANNEL_BINDINGS,
-                       &client_name, NULL, &authenticator_buff,
-                       &ret_flags, NULL, NULL );
 
-    if (major_status == GSS_S_COMPLETE) {
-       gss_buffer_desc client_name_buffer;
-
-#ifdef DEBUG1
-       log_ctx_flags( ret_flags );
-#endif
-       /* use gss_display_name on client_name */
-       major_status = gss_display_name( &minor_status, client_name,
-                               &client_name_buffer, (gss_OID *)NULL );
-       if (major_status == GSS_S_COMPLETE) {
-
-           sesskey_buff.value = sinfo->sessionkey;
-           sesskey_buff.length = sinfo->sessionkey_len;
-
-           gss_wrap (&minor_status, context_handle, 1, GSS_C_QOP_DEFAULT, &sesskey_buff, NULL, &wrap_buff); 
-           if ( minor_status == GSS_S_COMPLETE) {
-               sinfo->cryptedkey = malloc ( wrap_buff.length );
-               memcpy (sinfo->cryptedkey, wrap_buff.value, wrap_buff.length);
-               sinfo->cryptedkey_len = wrap_buff.length;
-           }
-           else {
-               log_status( "GSS wrap", major_status, minor_status );
-           }
-
-           if (wrap_buff.value)
-               gss_release_buffer( &minor_status, &wrap_buff );
-
-           u_int16_t auth_len = htons( authenticator_buff.length );
-           /* save the username... note that doing it this way is
-            * not the best idea: if a principal is truncated, a user could be
-            * impersonated
-            */
-           memcpy( username, client_name_buffer.value, 
-               MIN(client_name_buffer.length, ulen - 1));
-           username[MIN(client_name_buffer.length, ulen - 1)] = 0;
-       
-            LOG(log_debug, logtype_uams, "uams_gss.c :do_gss_auth: user is %s!", username );
-           /* copy the authenticator length into the reply buffer */
-           memcpy( rbuf, &auth_len, sizeof(auth_len) );
-           *rbuflen += sizeof(auth_len), rbuf += sizeof(auth_len);
-
-           /* copy the authenticator value into the reply buffer */
-           memcpy( rbuf, authenticator_buff.value, authenticator_buff.length );
-           *rbuflen += authenticator_buff.length;
-
-           gss_release_buffer( &minor_status, &client_name_buffer );
-       } else {
-           log_status( "display_name", major_status, minor_status );
-           ret = 1;
-       }
+    ret = accept_sec_context (&context_handle, server_creds, &ticket_buffer, 
+                          &client_name, &authenticator_buff);
 
-       
+    if (!ret) {
+        /* We succesfully acquired the secondary context, now get the 
+           username for afpd and gss_wrap the sessionkey */
+        if ( 0 == (ret = get_client_username(username, ulen, &client_name)) ) {
+            ret = wrap_sessionkey(context_handle, sinfo);
+        }
 
+        if (!ret) {
+            /* FIXME: Is copying the authenticator really necessary? 
+               Where is this documented? */
+            u_int16_t auth_len = htons( authenticator_buff.length );
 
-       /* Clean up after ourselves */
-        gss_release_name( &minor_status, &client_name );
+            /* copy the authenticator length into the reply buffer */
+            memcpy( rbuf, &auth_len, sizeof(auth_len) );
+            *rbuflen += sizeof(auth_len);
+            rbuf += sizeof(auth_len);
 
-       /* This will SIGSEGV, as it would free ibuf */
-        /*gss_release_buffer( &minor_status, &ticket_buffer );*/
+            /* copy the authenticator value into the reply buffer */
+            memcpy( rbuf, authenticator_buff.value, authenticator_buff.length );
+            *rbuflen += authenticator_buff.length;
+        }
 
+       /* Clean up after ourselves */
+        gss_release_name( &status, &client_name );
        if ( authenticator_buff.value)
-               gss_release_buffer( &minor_status, &authenticator_buff );
+           gss_release_buffer( &status, &authenticator_buff );
 
-        gss_delete_sec_context( &minor_status, 
-                       &context_handle, NULL );
-    } else {
-       log_status( "accept_sec_context", major_status, minor_status );
-        ret = 1;
-    }
-    gss_release_cred( &minor_status, &server_creds );
+        gss_delete_sec_context( &status, &context_handle, NULL );
+    } 
+    gss_release_cred( &status, &server_creds );
 
 cleanup_vars:
-    gss_release_name( &minor_status, &server_name );
+    gss_release_name( &status, &server_name );
     
     return ret;
 }
@@ -288,8 +471,7 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
     u_int16_t ticket_len;
     char *p;
     int rblen;
-    char *service;
-    int userlen, servicelen;
+    int userlen;
     struct session_info *sinfo;
 
     /* Apple's AFP 3.1 documentation specifies that this command
@@ -319,7 +501,7 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
     rblen = *rbuflen = 0;
 
     if (ibuflen < 3) {
-        LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: received incomplete packet", p);
+        LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: received incomplete packet");
        return AFPERR_PARAM;
     }
     ibuf++, ibuflen--; /* ?? */
@@ -329,21 +511,18 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
     ibuf += sizeof(login_id), ibuflen -= sizeof(login_id);
     login_id = ntohs( login_id );
 
+    /* get the username buffer from apfd */
     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, (void *) &username, &userlen) < 0)
         return AFPERR_MISC;
 
-    if (uam_afpserver_option(obj, UAM_OPTION_KRB5SERVICE, (void *)&service, &servicelen) < 0)
-       return AFPERR_MISC;
-
-    if (service == NULL) 
-       return AFPERR_MISC;
-
+    /* get the session_info structure from afpd. We need the session key */
     if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, (void *)&sinfo, NULL) < 0)
        return AFPERR_MISC;
 
     if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) {
-        LOG(log_info, logtype_uams, "internal error: sessionkey not set");
-        return AFPERR_PARAM;
+        /* Should never happen. Most likely way too old afpd version */
+        LOG(log_info, logtype_uams, "internal error: afpd's sessionkey not set");
+        return AFPERR_MISC;
     }
 
     /* We skip past the 'username' parameter because all that matters is the ticket */
@@ -360,21 +539,24 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
 
     LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: client thinks user is %s", p);
 
+    /* get the length of the ticket the client sends us */
     memcpy(&ticket_len, ibuf, sizeof(ticket_len));
     ibuf += sizeof(ticket_len); ibuflen -= sizeof(ticket_len);
     ticket_len = ntohs( ticket_len );
 
+    /* a little bounds checking */
     if (ticket_len > ibuflen) {
-        LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: invalid ticket length (%u > %u)", ticket_len, ibuflen);
+        LOG(log_info, logtype_uams,
+            "uams_gss.c :LoginCont: invalid ticket length (%u > %u)", ticket_len, ibuflen);
        return AFPERR_PARAM;
     }
 
-    if (!do_gss_auth(service, ibuf, ticket_len, rbuf, &rblen, username, userlen, sinfo)) {
-       char *at = strchr( username, '@' );
-
-       // Chop off the realm name
-       if (at)
-           *at = '\0';
+    /* now try to authenticate */
+    if (!do_gss_auth(obj, ibuf, ticket_len, rbuf, &rblen, username, userlen, sinfo)) {
+        /* We use the username we got back from the gssapi client_name.
+           Should we compare this to the username the client sent in the clear?
+           We know the character encoding of the cleartext username (UTF8), what
+           encoding is the gssapi name in? */
        if((pwd = uam_getname( obj, username, userlen )) == NULL) {
            LOG(log_info, logtype_uams, "uam_getname() failed for %s", username);
            return AFPERR_PARAM;
index b4c10d575d555c15d5abe59dd90259152598f744..e161b6859c1771c89288382b623b956808c09799 100644 (file)
@@ -44,6 +44,8 @@
 #define UAM_OPTION_MACCHARSET   (1 << 10) /* mac charset handle */
 #define UAM_OPTION_UNIXCHARSET  (1 << 11) /* unix charset handle */
 #define UAM_OPTION_SESSIONINFO  (1 << 12) /* unix charset handle */
+#define UAM_OPTION_KRB5REALM    (1 << 13) /* krb realm */
+#define UAM_OPTION_FQDN         (1 << 14) /* fully qualified name */
 
 /* some password options. you pass these in the length parameter and
  * get back the corresponding option. not all of these are implemented. */