]> arthur.barton.de Git - netatalk.git/commitdiff
Formatting/logging for uams_gss
authorJamie Gilbertson <jamie.gilbertson@luniv.ca>
Tue, 13 Mar 2012 02:34:32 +0000 (20:34 -0600)
committerFrank Lahm <franklahm@googlemail.com>
Mon, 19 Mar 2012 11:48:24 +0000 (12:48 +0100)
Changed formatting to be consistent.
Added convenience macros for logging.
Log which service principal the client chose to use.

Signed-off-by: Jamie Gilbertson <jamie.gilbertson@luniv.ca>
etc/uams/uams_gss.c

index 47763a8483dd7a2887cc10a801ad419f3e42f5c7..f8cfc1af1434c0ad7384456e9340fe5fdd38d379 100644 (file)
@@ -10,6 +10,7 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <gssapi.h>
 #endif // HAVE_GSSAPI_GSSAPI_H
 
-static void log_status( char *s, OM_uint32 major_status,
-                        OM_uint32 minor_status )
+#define LOG_UAMS(log_level, ...) \
+    LOG(log_level, logtype_uams, __VA_ARGS__)
+
+#define LOG_LOGINCONT(log_level, ...) \
+    LOG_UAMS(log_level, "FPLoginCont: " __VA_ARGS__)
+
+static void log_status(char *s,
+                       OM_uint32 major_status,
+                       OM_uint32 minor_status)
 {
     gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
     OM_uint32 min_status, maj_status;
@@ -39,19 +47,20 @@ static void log_status( char *s, OM_uint32 major_status,
         maj_status = gss_display_status( &min_status, major_status,
                                          GSS_C_GSS_CODE, GSS_C_NULL_OID,
                                          &maj_ctx, &msg );
-        LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
-            (int)msg.length, msg.value, strerror(errno));
+        LOG_UAMS(log_error, "%s %.*s (error %s)",
+                 s, msg.length, msg.value, strerror(errno));
         gss_release_buffer(&min_status, &msg);
 
         if (!maj_ctx)
             break;
     }
+
     while (1) {
         maj_status = gss_display_status( &min_status, minor_status,
-                                         GSS_C_MECH_CODE, GSS_C_NULL_OID, // gss_mech_krb5,
+                                         GSS_C_MECH_CODE, GSS_C_NULL_OID,
                                          &min_ctx, &msg );
-        LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
-            (int)msg.length, msg.value, strerror(errno));
+        LOG_UAMS(log_error, "%s %.*s (error %s)",
+                 s, msg.length, msg.value, strerror(errno));
         gss_release_buffer(&min_status, &msg);
 
         if (!min_ctx)
@@ -59,33 +68,66 @@ static void log_status( char *s, OM_uint32 major_status,
     }
 }
 
-
-static void log_ctx_flags( OM_uint32 flags )
+static void log_ctx_flags(OM_uint32 flags)
 {
-#ifdef DEBUG
     if (flags & GSS_C_DELEG_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_DELEG_FLAG" );
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_DELEG_FLAG");
     if (flags & GSS_C_MUTUAL_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_MUTUAL_FLAG" );
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_MUTUAL_FLAG");
     if (flags & GSS_C_REPLAY_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_REPLAY_FLAG" );
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_REPLAY_FLAG");
     if (flags & GSS_C_SEQUENCE_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_SEQUENCE_FLAG" );
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_SEQUENCE_FLAG");
     if (flags & GSS_C_CONF_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_CONF_FLAG" );
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_CONF_FLAG");
     if (flags & GSS_C_INTEG_FLAG)
-        LOG(log_debug, logtype_uams, "uams_gss.c :context flag: GSS_C_INTEG_FLAG" );
-#endif
+        LOG_LOGINCONT(log_debug, "context flag: GSS_C_INTEG_FLAG");
 }
 
+static void log_service_name(gss_ctx_id_t context)
+{
+    OM_uint32 major_status = 0, minor_status = 0;
+    gss_name_t service_name;
+    gss_buffer_desc service_name_buffer;
+
+    major_status = gss_inquire_context(&minor_status,
+                                       context,
+                                       NULL,
+                                       &service_name,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL);
+    if (major_status != GSS_S_COMPLETE) {
+        log_status("gss_inquire_context", major_status, minor_status);
+        return;
+    }
+
+    major_status = gss_display_name(&minor_status,
+                                    service_name,
+                                    &service_name_buffer,
+                                    NULL);
+    if (major_status == GSS_S_COMPLETE) {
+        LOG_LOGINCONT(log_debug,
+                      "service principal is `%s'",
+                      service_name_buffer.value);
+
+        gss_release_buffer(&minor_status, &service_name_buffer);
+    } else
+        log_status("gss_display_name", major_status, minor_status);
 
-/* get the username */
-static int get_client_username(char *username, int ulen, gss_name_t *client_name)
+    gss_release_name(&minor_status, &service_name);
+}
+
+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;
+    int ret = 0;
 
     /*
      * To extract the unix username, use gss_display_name on client_name.
@@ -95,39 +137,42 @@ static int get_client_username(char *username, int ulen, gss_name_t *client_name
      * the username before copying it to afpd's buffer.
      */
 
-    major_status = gss_display_name( &minor_status, *client_name,
-                                     &client_name_buffer, (gss_OID *)NULL );
+    major_status = gss_display_name(&minor_status,
+                                    *client_name,
+                                    &client_name_buffer,
+                                    NULL);
     if (major_status != GSS_S_COMPLETE) {
-        log_status( "display_name", major_status, minor_status );
+        log_status("gss_display_name", major_status, minor_status);
         return 1;
     }
 
-    LOG(log_debug, logtype_uams, "get_client_username: user is `%s'", client_name_buffer.value);
+    LOG_LOGINCONT(log_debug,
+                  "user principal is `%s'",
+                  client_name_buffer.value);
 
     /* chop off realm */
-    p = strchr( client_name_buffer.value, '@' );
+    p = strchr(client_name_buffer.value, '@');
     if (p)
         *p = 0;
     /* FIXME: chop off instance? */
-    p = strchr( client_name_buffer.value, '/' );
+    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 ) {
+    size_t cnblen = strlen(client_name_buffer.value);
+    if (cnblen >= 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);
+        LOG_LOGINCONT(log_info,
+                      "username `%s' too long (%d)",
+                      client_name_buffer.value, cnblen);
         ret = 1;
-    }
-    else {
+    } 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 );
+    gss_release_buffer(&minor_status, &client_name_buffer);
 
     return ret;
 }
@@ -135,9 +180,9 @@ static int get_client_username(char *username, int ulen, gss_name_t *client_name
 /* wrap afpd's sessionkey */
 static int wrap_sessionkey(gss_ctx_id_t context, struct session_info *sinfo)
 {
-    OM_uint32 status = 0;
-    int ret=0;
+    OM_uint32 major_status = 0, minor_status = 0;
     gss_buffer_desc sesskey_buff, wrap_buff;
+    int ret = 0;
 
     /*
      * gss_wrap afpd's session_key.
@@ -145,79 +190,92 @@ static int wrap_sessionkey(gss_ctx_id_t context, struct session_info *sinfo)
      * 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);
+    major_status = gss_wrap(&minor_status,
+                            context,
+                            true,
+                            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 );
+    if (major_status != GSS_S_COMPLETE) {
+        log_status("gss_wrap", major_status, minor_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);
+    if (NULL == (sinfo->cryptedkey = malloc(wrap_buff.length))) {
+        LOG_UAMS(log_error,
+                 "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);
+        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 );
+    gss_release_buffer(&minor_status, &wrap_buff);
 
     return ret;
 }
 
-/*-------------*/
-static int accept_sec_context (gss_ctx_id_t *context,
-                               gss_buffer_desc *ticket_buffer, gss_name_t *client_name,
-                               gss_buffer_desc *authenticator_buff)
+static int accept_sec_context(gss_ctx_id_t *context,
+                              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;
+    OM_uint32 major_status = 0, minor_status = 0, flags = 0;
 
     /* Initialize autheticator buffer. */
     authenticator_buff->length = 0;
     authenticator_buff->value = NULL;
 
-    LOG(log_debug, logtype_uams, "accept_context: accepting context (ticketlen: %u)",
-        ticket_buffer->length);
+    LOG_LOGINCONT(log_debug,
+                  "accepting context (ticketlen: %u)",
+                  ticket_buffer->length);
 
     /*
      * Try to accept the secondary context using the token in ticket_buffer.
      * We don't care about the principals or mechanisms used, nor for the time.
      * We don't act as a proxy either.
      */
-    major_status = gss_accept_sec_context( &minor_status, context,
-                                           GSS_C_NO_CREDENTIAL, ticket_buffer, GSS_C_NO_CHANNEL_BINDINGS,
-                                           client_name, NULL, authenticator_buff,
-                                           &ret_flags, NULL, NULL );
+    major_status = gss_accept_sec_context(&minor_status,
+                                          context,
+                                          GSS_C_NO_CREDENTIAL,
+                                          ticket_buffer,
+                                          GSS_C_NO_CHANNEL_BINDINGS,
+                                          client_name,
+                                          NULL,
+                                          authenticator_buff,
+                                          &flags,
+                                          NULL,
+                                          NULL);
 
     if (major_status != GSS_S_COMPLETE) {
-        log_status( "accept_sec_context", major_status, minor_status );
+        log_status("gss_accept_sec_context", major_status, minor_status);
         return 1;
     }
-    log_ctx_flags( ret_flags );
+
+    log_ctx_flags(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,
+static int do_gss_auth(void *obj,
+                       char *ibuf, size_t ibuflen,
+                       char *rbuf, int *rbuflen,
+                       char *username, size_t ulen,
                        struct session_info *sinfo )
 {
     OM_uint32 status = 0;
     gss_name_t client_name;
-    gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
+    gss_ctx_id_t context = GSS_C_NO_CONTEXT;
     gss_buffer_desc ticket_buffer, authenticator_buff;
     int ret = 0;
 
@@ -226,19 +284,22 @@ static int do_gss_auth(void *obj, char *ibuf, int ticket_len,
      * 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.length = ibuflen;
     ticket_buffer.value = ibuf;
 
-    if ((ret = accept_sec_context(&context_handle, &ticket_buffer, 
-                                  &client_name, &authenticator_buff)))
+    if ((ret = accept_sec_context(&context,
+                                  &ticket_buffer,
+                                  &client_name,
+                                  &authenticator_buff)))
         return ret;
+    log_service_name(context);
 
     /* We succesfully acquired the secondary context, now get the
        username for afpd and gss_wrap the sessionkey */
     if ((ret = get_client_username(username, ulen, &client_name)))
         goto cleanup_client_name;
 
-    if ((ret = wrap_sessionkey(context_handle, sinfo)))
+    if ((ret = wrap_sessionkey(context, sinfo)))
         goto cleanup_client_name;
 
     /* Authenticated, construct the reply using:
@@ -246,21 +307,21 @@ static int do_gss_auth(void *obj, char *ibuf, int ticket_len,
      * authenticator
      */
     /* copy the authenticator length into the reply buffer */
-    uint16_t auth_len = htons( authenticator_buff.length );
-    memcpy( rbuf, &auth_len, sizeof(auth_len) );
+    uint16_t auth_len = htons(authenticator_buff.length);
+    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 );
+    memcpy(rbuf, authenticator_buff.value, authenticator_buff.length);
     *rbuflen += authenticator_buff.length;
 
 cleanup_client_name:
-    gss_release_name( &status, &client_name );
+    gss_release_name(&status, &client_name);
 
 cleanup_context:
-    gss_release_buffer( &status, &authenticator_buff );
-    gss_delete_sec_context( &status, &context_handle, NULL );
+    gss_release_buffer(&status, &authenticator_buff);
+    gss_delete_sec_context(&status, &context, NULL);
 
     return ret;
 }
@@ -272,25 +333,25 @@ cleanup_context:
  * login-session id. None of the data provided by the client up to this
  * point is trustworthy as we'll have a signed ticket to parse in logincont.
  */
-static int gss_login(void *obj, struct passwd **uam_pwd,
+static int gss_login(void *obj,
+                     struct passwd **uam_pwd,
                      char *ibuf, size_t ibuflen,
                      char *rbuf, size_t *rbuflen)
 {
-
-    uint16_t  temp16;
-
     *rbuflen = 0;
 
     /* The reply contains a two-byte ID value - note
      * that Apple's implementation seems to always return 1 as well
      */
-    temp16 = htons( 1 );
+    uint16_t temp16 = htons(1);
     memcpy(rbuf, &temp16, sizeof(temp16));
     *rbuflen += sizeof(temp16);
+
     return AFPERR_AUTHCONT;
 }
 
-static int gss_logincont(void *obj, struct passwd **uam_pwd,
+static int gss_logincont(void *obj,
+                         struct passwd **uam_pwd,
                          char *ibuf, size_t ibuflen,
                          char *rbuf, size_t *rbuflen)
 {
@@ -307,7 +368,8 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
      * takes the following format:
      * pad (byte)
      * id returned in LoginExt response (uint16_t)
-     * username (format unspecified) padded, when necessary, to end on an even boundary
+     * username (format unspecified)
+     *   padded, when necessary, to end on an even boundary
      * ticket length (uint16_t)
      * ticket
      */
@@ -330,27 +392,27 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
     rblen = *rbuflen = 0;
 
     if (ibuflen < 1 +sizeof(login_id)) {
-        LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: received incomplete packet");
+        LOG_LOGINCONT(log_info, "received incomplete packet");
         return AFPERR_PARAM;
     }
     ibuf++, ibuflen--; /* ?? */
 
     /* 2 byte ID from LoginExt -- always '00 01' in this implementation */
-    memcpy( &login_id, ibuf, sizeof(login_id) );
+    memcpy(&login_id, ibuf, sizeof(login_id));
     ibuf += sizeof(login_id), ibuflen -= sizeof(login_id);
-    login_id = ntohs( 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)
+    if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &userlen) < 0)
         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)
+    if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, &sinfo, NULL) < 0)
         return AFPERR_MISC;
 
     if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) {
         /* Should never happen. Most likely way too old afpd version */
-        LOG(log_info, logtype_uams, "internal error: afpd's sessionkey not set");
+        LOG_LOGINCONT(log_error, "internal error: afpd's sessionkey not set");
         return AFPERR_MISC;
     }
 
@@ -358,7 +420,7 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
     p = ibuf;
     while ( *ibuf && ibuflen ) { ibuf++, ibuflen--; }
     if (ibuflen < 4) {
-        LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: user is %s, no ticket", p);
+        LOG_LOGINCONT(log_info, "user is %s, no ticket", p);
         return AFPERR_PARAM;
     }
 
@@ -366,23 +428,24 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
 
     if ((ibuf - p + 1) % 2) ibuf++, ibuflen--; /* deal with potential padding */
 
-    LOG(log_debug, logtype_uams, "uams_gss.c :LoginCont: client thinks user is %s", p);
+    LOG_LOGINCONT(log_debug, "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 );
+    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_LOGINCONT(log_info,
+                      "invalid ticket length (%u > %u)",
+                      ticket_len, ibuflen);
         return AFPERR_PARAM;
     }
 
     /* now try to authenticate */
     if (do_gss_auth(obj, ibuf, ticket_len, rbuf, &rblen, username, userlen, sinfo)) {
-        LOG(log_info, logtype_uams, "do_gss_auth failed" );
+        LOG_LOGINCONT(log_info, "do_gss_auth() failed" );
         *rbuflen = 0;
         return AFPERR_MISC;
     }
@@ -392,13 +455,14 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
        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);
+        LOG_LOGINCONT(log_info, "uam_getname() failed for %s", username);
         return AFPERR_NOTAUTH;
     }
     if (uam_checkuser(pwd) < 0) {
-        LOG(log_info, logtype_uams, "%s not a valid user", username);
+        LOG_LOGINCONT(log_info, "`%s'' not a valid user", username);
         return AFPERR_NOTAUTH;
     }
+
     *rbuflen = rblen;
     *uam_pwd = pwd;
     return AFP_OK;
@@ -408,7 +472,9 @@ static int gss_logincont(void *obj, struct passwd **uam_pwd,
 static void gss_logout() {
 }
 
-static int gss_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
+static int gss_login_ext(void *obj,
+                         char *uname,
+                         struct passwd **uam_pwd,
                          char *ibuf, size_t ibuflen,
                          char *rbuf, size_t *rbuflen)
 {
@@ -429,5 +495,6 @@ static void uam_cleanup(void)
 UAM_MODULE_EXPORT struct uam_export uams_gss = {
     UAM_MODULE_SERVER,
     UAM_MODULE_VERSION,
-    uam_setup, uam_cleanup
+    uam_setup,
+    uam_cleanup
 };