]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
gssapi: Code cleanups. Logging error level changes.
authorTimo Sirainen <tss@iki.fi>
Tue, 7 Jul 2009 23:48:26 +0000 (19:48 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 7 Jul 2009 23:48:26 +0000 (19:48 -0400)
--HG--
branch : HEAD

src/auth/mech-gssapi.c

index f8bba6edbbc628b86114e58cf14c7ee048145af6..06fde8dd20d686f32967f7207d38e214aa37e98c 100644 (file)
@@ -80,21 +80,19 @@ static void auth_request_log_gss_error(struct auth_request *request,
                                       const char *description)
 {
        OM_uint32 message_context = 0;
-       OM_uint32 major_status, minor_status;
+       OM_uint32 minor_status;
        gss_buffer_desc status_string;
 
        do {
-               major_status = gss_display_status(&minor_status, status_value, 
-                                                 status_type, GSS_C_NO_OID,
-                                                 &message_context,
-                                                 &status_string);
-       
-               auth_request_log_error(request, "gssapi",
+               (void)gss_display_status(&minor_status, status_value,
+                                        status_type, GSS_C_NO_OID,
+                                        &message_context, &status_string);
+
+               auth_request_log_info(request, "gssapi",
                        "While %s: %s", description,
                        str_sanitize(status_string.value, (size_t)-1));
 
-               major_status = gss_release_buffer(&minor_status,
-                                                 &status_string);
+               (void)gss_release_buffer(&minor_status, &status_string);
        } while (message_context != 0);
 }
 
@@ -128,8 +126,8 @@ static struct auth_request *mech_gssapi_auth_new(void)
        return &request->auth_request;
 }
 
-static OM_uint32 obtain_service_credentials(struct auth_request *request,
-                                           gss_cred_id_t *ret)
+static OM_uint32
+obtain_service_credentials(struct auth_request *request, gss_cred_id_t *ret_r)
 {
        OM_uint32 major_status, minor_status;
        string_t *principal_name;
@@ -143,9 +141,9 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request,
        }
 
        if (strcmp(request->auth->set->gssapi_hostname, "$ALL") == 0) {
-               auth_request_log_info(request, "gssapi",
-                                     "Using all keytab entries");
-               *ret = GSS_C_NO_CREDENTIAL;
+               auth_request_log_debug(request, "gssapi",
+                                      "Using all keytab entries");
+               *ret_r = GSS_C_NO_CREDENTIAL;
                return GSS_S_COMPLETE;
        }
 
@@ -162,7 +160,7 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request,
        str_append_c(principal_name, '@');
        str_append(principal_name, request->auth->set->gssapi_hostname);
 
-       auth_request_log_info(request, "gssapi",
+       auth_request_log_debug(request, "gssapi",
                "Obtaining credentials for %s", str_c(principal_name));
 
        inbuf.length = str_len(principal_name);
@@ -171,7 +169,6 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request,
        major_status = gss_import_name(&minor_status, &inbuf, 
                                       GSS_C_NT_HOSTBASED_SERVICE,
                                       &gss_principal);
-
        str_free(&principal_name);
 
        if (GSS_ERROR(major_status)) {
@@ -183,8 +180,7 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request,
 
        major_status = gss_acquire_cred(&minor_status, gss_principal, 0, 
                                        GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
-                                       ret, NULL, NULL);
-
+                                       ret_r, NULL, NULL);
        if (GSS_ERROR(major_status)) {
                auth_request_log_gss_error(request, major_status,
                                           GSS_C_GSS_CODE,
@@ -196,11 +192,9 @@ static OM_uint32 obtain_service_credentials(struct auth_request *request,
        }
 
        gss_release_name(&minor_status, &gss_principal);
-
        return major_status;
 }
 
-#ifndef HAVE___GSS_USEROK
 static gss_name_t
 import_name(struct auth_request *request, void *str, size_t len)
 {
@@ -210,22 +204,18 @@ import_name(struct auth_request *request, void *str, size_t len)
 
        name_buf.value = str;
        name_buf.length = len;
-       major_status = gss_import_name(&minor_status,
-                                      &name_buf,
-                                      GSS_C_NO_OID,
-                                      &name);
+       major_status = gss_import_name(&minor_status, &name_buf,
+                                      GSS_C_NO_OID, &name);
        if (GSS_ERROR(major_status)) {
                auth_request_log_gss_error(request, major_status,
                                           GSS_C_GSS_CODE, "gss_import_name");
                return GSS_C_NO_NAME;
        }
-
        return name;
 }
-#endif
 
-static void gssapi_sec_context(struct gssapi_auth_request *request,
-                              gss_buffer_desc inbuf)
+static int gssapi_sec_context(struct gssapi_auth_request *request,
+                             gss_buffer_desc inbuf)
 {
        OM_uint32 major_status, minor_status;
        gss_buffer_desc outbuf;
@@ -251,36 +241,41 @@ static void gssapi_sec_context(struct gssapi_auth_request *request,
                auth_request_log_gss_error(&request->auth_request, minor_status,
                                           GSS_C_MECH_CODE,
                                           "processing incoming data");
-
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        } 
 
-       if (major_status == GSS_S_COMPLETE) {
+       switch (major_status) {
+       case GSS_S_COMPLETE:
                request->sasl_gssapi_state = GSS_STATE_WRAP;
-               auth_request_log_info(&request->auth_request, "gssapi", 
-                                     "security context state completed.");
-       } else {
-               auth_request_log_info(&request->auth_request, "gssapi", 
-                                     "Processed incoming packet correctly, "
-                                     "waiting for another.");
+               auth_request_log_debug(&request->auth_request, "gssapi",
+                                      "security context state completed.");
+               break;
+       case GSS_S_CONTINUE_NEEDED:
+               auth_request_log_debug(&request->auth_request, "gssapi",
+                                      "Processed incoming packet correctly, "
+                                      "waiting for another.");
+               break;
+       default:
+               auth_request_log_error(&request->auth_request, "gssapi",
+                       "Received unexpected major status %d", major_status);
+               break;
        }
 
        request->auth_request.callback(&request->auth_request,
                                       AUTH_CLIENT_RESULT_CONTINUE,
                                       outbuf.value, outbuf.length);
-
-       major_status = gss_release_buffer(&minor_status, &outbuf);
+       (void)gss_release_buffer(&minor_status, &outbuf);
+       return 0;
 }
 
-static void gssapi_wrap(struct gssapi_auth_request *request,
-                       gss_buffer_desc inbuf)
+static int
+gssapi_wrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf)
 {
        OM_uint32 major_status, minor_status;
        gss_buffer_desc outbuf;
        unsigned char ret[4];
 
-       /* The clients return data should be empty here */
+       /* The client's return data should be empty here */
        
        /* Only authentication, no integrity or confidentiality
           protection (yet?) */
@@ -301,20 +296,19 @@ static void gssapi_wrap(struct gssapi_auth_request *request,
                        GSS_C_GSS_CODE, "sending security layer negotiation");
                auth_request_log_gss_error(&request->auth_request, minor_status,
                        GSS_C_MECH_CODE, "sending security layer negotiation");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        } 
 
-       auth_request_log_info(&request->auth_request, "gssapi", 
-                             "Negotiated security layer");
+       auth_request_log_debug(&request->auth_request, "gssapi",
+                              "Negotiated security layer");
 
        request->auth_request.callback(&request->auth_request,
                                       AUTH_CLIENT_RESULT_CONTINUE,
                                       outbuf.value, outbuf.length);
 
-       major_status = gss_release_buffer(&minor_status, &outbuf);
-
+       (void)gss_release_buffer(&minor_status, &outbuf);
        request->sasl_gssapi_state = GSS_STATE_UNWRAP;
+       return 0;
 }
 
 #ifdef USE_KRB5_USEROK
@@ -337,16 +331,16 @@ gssapi_krb5_userok(struct gssapi_auth_request *request, gss_name_t name,
        if (major_status != GSS_S_COMPLETE) {
                auth_request_log_gss_error(&request->auth_request, major_status,
                                           GSS_C_GSS_CODE,
-                                          "gssapi_krb5_userok");
+                                          "gss_display_name");
                return FALSE;
        }
        if (name_type != GSS_KRB5_NT_PRINCIPAL_NAME && check_name_type) {
-               auth_request_log_error(&request->auth_request, "gssapi",
-                                      "OID not kerberos principal name");
+               auth_request_log_info(&request->auth_request, "gssapi",
+                                     "OID not kerberos principal name");
                return FALSE;
        }
        princ_display_name = t_strndup(princ_name.value, princ_name.length);
-       gss_release_buffer(&minor_status, &princ_name);
+       (void)gss_release_buffer(&minor_status, &princ_name);
 
        /* Init a krb5 context and parse the principal username */
        krb5_err = krb5_init_context(&ctx);
@@ -360,9 +354,9 @@ gssapi_krb5_userok(struct gssapi_auth_request *request, gss_name_t name,
                /* writing the error string would be better, but we probably
                   rarely get here and there doesn't seem to be a standard
                   way of getting it */
-               auth_request_log_error(&request->auth_request, "gssapi",
-                                      "krb5_parse_name() failed: %d",
-                                      (int)krb5_err);
+               auth_request_log_info(&request->auth_request, "gssapi",
+                                     "krb5_parse_name() failed: %d",
+                                     (int)krb5_err);
        } else {
                /* See if the principal is authorized to act as the
                   specified user */
@@ -374,104 +368,99 @@ gssapi_krb5_userok(struct gssapi_auth_request *request, gss_name_t name,
 }
 #endif
 
-static void gssapi_unwrap(struct gssapi_auth_request *request,
-                         gss_buffer_desc inbuf)
+static int
+gssapi_unwrap(struct gssapi_auth_request *request, gss_buffer_desc inbuf)
 {
        OM_uint32 major_status, minor_status;
        gss_buffer_desc outbuf;
-#if defined(HAVE___GSS_USEROK) || !defined(USE_KRB5_USEROK)
-       int equal_authn_authz = 0;
+       unsigned char *name;
+       unsigned int name_len;
+#if defined(HAVE___GSS_USEROK)
+       int login_ok;
+#elif !defined(USE_KRB5_USEROK)
+       int equal_authn_authz;
 #endif
-       major_status = gss_unwrap(&minor_status, request->gss_ctx, 
+
+       major_status = gss_unwrap(&minor_status, request->gss_ctx,
                                  &inbuf, &outbuf, NULL, NULL);
 
        if (GSS_ERROR(major_status)) {
                auth_request_log_gss_error(&request->auth_request, major_status,
                                           GSS_C_GSS_CODE,
                                           "final negotiation: gss_unwrap");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        } 
 
+       /* outbuf[0] contains bitmask for selected security layer,
+          outbuf[1..3] contains maximum output_message size */
        if (outbuf.length <= 4) {
                auth_request_log_error(&request->auth_request, "gssapi",
                                       "Invalid response length");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
+       }
+       name = (unsigned char *)outbuf.value + 4;
+       name_len = outbuf.length - 4;
+
+       request->auth_request.user =
+               p_strndup(request->auth_request.pool, name, name_len);
+
+       request->authz_name = import_name(&request->auth_request,
+                                         name, name_len);
+       if (request->authz_name == GSS_C_NO_NAME) {
+               auth_request_log_info(&request->auth_request, "gssapi",
+                                     "no authz_name");
+               return -1;
        }
 
 #ifdef HAVE___GSS_USEROK
        /* Solaris __gss_userok() correctly handles cross-realm
           authentication. */
-       request->auth_request.user =
-               p_strndup(request->auth_request.pool,
-                         (unsigned char *)outbuf.value + 4,
-                         outbuf.length - 4);
-
        major_status = __gss_userok(&minor_status, request->authn_name,
                                    request->auth_request.user,
-                                   &equal_authn_authz);
+                                   &login_ok);
        if (GSS_ERROR(major_status)) {
                auth_request_log_gss_error(&request->auth_request, major_status,
                                           GSS_C_GSS_CODE,
                                           "__gss_userok failed");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        } 
 
-       if (equal_authn_authz == 0) {
-               auth_request_log_error(&request->auth_request, "gssapi",
-                                      "credentials not valid");
-
-               auth_request_fail(&request->auth_request);
-               return;
-       }
-#else
-       request->authz_name = import_name(&request->auth_request,
-                                         (unsigned char *)outbuf.value + 4,
-                                         outbuf.length - 4);
-       if ((request->authn_name == GSS_C_NO_NAME) ||
-           (request->authz_name == GSS_C_NO_NAME)) {
-               /* XXX (pod): is this check necessary? */
-               auth_request_log_error(&request->auth_request, "gssapi",
-                       "one of authn_name or authz_name not determined");
-               auth_request_fail(&request->auth_request);
-               return;
+       if (login_ok == 0) {
+               auth_request_log_info(&request->auth_request, "gssapi",
+                                     "credentials not valid");
+               return -1;
        }
-
-       request->auth_request.user =
-               p_strndup(request->auth_request.pool,
-                         (unsigned char *)outbuf.value + 4,
-                         outbuf.length - 4);
-
-#ifdef USE_KRB5_USEROK
+#elif defined(USE_KRB5_USEROK)
        if (!gssapi_krb5_userok(request, request->authn_name, TRUE)) {
-               auth_request_log_error(&request->auth_request, "gssapi",
+               auth_request_log_info(&request->auth_request, "gssapi",
                        "authn_name not authorized");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        }
-       
+
        if (!gssapi_krb5_userok(request, request->authz_name, FALSE)) {
-               auth_request_log_error(&request->auth_request, "gssapi",
+               auth_request_log_info(&request->auth_request, "gssapi",
                        "authz_name not authorized");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        }
 #else
        major_status = gss_compare_name(&minor_status,
                                        request->authn_name,
                                        request->authz_name,
                                        &equal_authn_authz);
+       if (GSS_ERROR(major_status)) {
+               auth_request_log_gss_error(&request->auth_request, major_status,
+                                          GSS_C_GSS_CODE,
+                                          "gss_compare_name failed");
+               return -1;
+       }
        if (equal_authn_authz == 0) {
-               auth_request_log_error(&request->auth_request, "gssapi",
+               auth_request_log_info(&request->auth_request, "gssapi",
                        "authn_name and authz_name differ: not supported");
-               auth_request_fail(&request->auth_request);
-               return;
+               return -1;
        }
-#endif
 #endif
        auth_request_success(&request->auth_request, NULL, 0);
+       return 0;
 }
 
 static void
@@ -481,30 +470,36 @@ mech_gssapi_auth_continue(struct auth_request *request,
        struct gssapi_auth_request *gssapi_request = 
                (struct gssapi_auth_request *)request;
        gss_buffer_desc inbuf;
+       int ret;
 
        inbuf.value = (void *)data;
        inbuf.length = data_size;
 
        switch (gssapi_request->sasl_gssapi_state) {
        case GSS_STATE_SEC_CONTEXT:
-               gssapi_sec_context(gssapi_request, inbuf);
+               ret = gssapi_sec_context(gssapi_request, inbuf);
                break;
        case GSS_STATE_WRAP:
-               gssapi_wrap(gssapi_request, inbuf);
+               ret = gssapi_wrap(gssapi_request, inbuf);
                break;
        case GSS_STATE_UNWRAP:
-               gssapi_unwrap(gssapi_request, inbuf);
+               ret = gssapi_unwrap(gssapi_request, inbuf);
                break;
-       } 
+       default:
+               ret = -1;
+               i_unreached();
+       }
+       if (ret < 0)
+               auth_request_fail(request);
 }
 
 static void
 mech_gssapi_auth_initial(struct auth_request *request,
-                      const unsigned char *data, size_t data_size)
+                        const unsigned char *data, size_t data_size)
 {
-       OM_uint32 major_status;
        struct gssapi_auth_request *gssapi_request = 
                (struct gssapi_auth_request *)request;
+       OM_uint32 major_status;
        
        major_status =
                obtain_service_credentials(request,
@@ -528,29 +523,27 @@ mech_gssapi_auth_initial(struct auth_request *request,
        }
 }
 
-
 static void
 mech_gssapi_auth_free(struct auth_request *request)
 {
-       OM_uint32 major_status, minor_status;
-       struct gssapi_auth_request *gssapi_request = 
+       struct gssapi_auth_request *gssapi_request =
                (struct gssapi_auth_request *)request;
+       OM_uint32 minor_status;
 
        if (gssapi_request->gss_ctx != GSS_C_NO_CONTEXT) {
-               major_status = gss_delete_sec_context(&minor_status,
-                                                     &gssapi_request->gss_ctx,
-                                                     GSS_C_NO_BUFFER);
+               (void)gss_delete_sec_context(&minor_status,
+                                            &gssapi_request->gss_ctx,
+                                            GSS_C_NO_BUFFER);
        }
 
-       major_status = gss_release_cred(&minor_status,
-                                       &gssapi_request->service_cred);
+       (void)gss_release_cred(&minor_status, &gssapi_request->service_cred);
        if (gssapi_request->authn_name != GSS_C_NO_NAME) {
-               major_status = gss_release_name(&minor_status,
-                                               &gssapi_request->authn_name);
+               (void)gss_release_name(&minor_status,
+                                      &gssapi_request->authn_name);
        }
        if (gssapi_request->authz_name != GSS_C_NO_NAME) {
-               major_status = gss_release_name(&minor_status,
-                                               &gssapi_request->authz_name);
+               (void)gss_release_name(&minor_status,
+                                      &gssapi_request->authz_name);
        }
        pool_unref(&request->pool);
 }