Mercurial > dovecot > original-hg > dovecot-1.2
changeset 9196:4172004c1958 HEAD
gssapi: Code cleanups. Logging error level changes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 07 Jul 2009 19:47:48 -0400 |
parents | 072a44932976 |
children | a5c5a912769e |
files | src/auth/mech-gssapi.c |
diffstat | 1 files changed, 121 insertions(+), 128 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/mech-gssapi.c Tue Jul 07 18:36:02 2009 -0400 +++ b/src/auth/mech-gssapi.c Tue Jul 07 19:47:48 2009 -0400 @@ -80,21 +80,19 @@ 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); } @@ -132,8 +130,8 @@ 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; @@ -142,9 +140,9 @@ const char *service_name; if (strcmp(request->auth->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; } @@ -161,7 +159,7 @@ str_append_c(principal_name, '@'); str_append(principal_name, request->auth->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); @@ -170,7 +168,6 @@ major_status = gss_import_name(&minor_status, &inbuf, GSS_C_NT_HOSTBASED_SERVICE, &gss_principal); - str_free(&principal_name); if (GSS_ERROR(major_status)) { @@ -182,8 +179,7 @@ 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, @@ -195,11 +191,9 @@ } 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) { @@ -209,22 +203,18 @@ 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; @@ -250,36 +240,41 @@ 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?) */ @@ -300,20 +295,19 @@ 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 @@ -336,16 +330,16 @@ 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); @@ -359,9 +353,9 @@ /* 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 */ @@ -373,104 +367,99 @@ } #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; + if (login_ok == 0) { + auth_request_log_info(&request->auth_request, "gssapi", + "credentials not valid"); + return -1; } -#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; +#elif defined(USE_KRB5_USEROK) + if (!gssapi_krb5_userok(request, request->authn_name, TRUE)) { + auth_request_log_info(&request->auth_request, "gssapi", + "authn_name not authorized"); + return -1; } - request->auth_request.user = - p_strndup(request->auth_request.pool, - (unsigned char *)outbuf.value + 4, - outbuf.length - 4); - -#ifdef USE_KRB5_USEROK - if (!gssapi_krb5_userok(request, request->authn_name, TRUE)) { - auth_request_log_error(&request->auth_request, "gssapi", - "authn_name not authorized"); - auth_request_fail(&request->auth_request); - return; - } - 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 @@ -480,30 +469,36 @@ 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, @@ -527,29 +522,27 @@ } } - 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); }