diff -ru dovecot-jv/src/auth/mech-gssapi.c dovecot-jv-pod/src/auth/mech-gssapi.c --- dovecot-jv/src/auth/mech-gssapi.c 2005-10-19 18:58:34.000000000 +0100 +++ dovecot-jv-pod/src/auth/mech-gssapi.c 2005-10-20 16:03:30.000000000 +0100 @@ -28,6 +28,14 @@ #include +/* Non-zero flags defined in RFC 2222 */ +enum sasl_gssapi_qop { + SASL_GSSAPI_QOP_UNSPECIFIED = 0x00, + SASL_GSSAPI_QOP_AUTH_ONLY = 0x01, + SASL_GSSAPI_QOP_AUTH_INT = 0x02, + SASL_GSSAPI_QOP_AUTH_CONF = 0x04 +}; + struct gssapi_auth_request { struct auth_request auth_request; gss_ctx_id_t gss_ctx; @@ -39,7 +47,8 @@ GSS_STATE_UNWRAP } sasl_gssapi_state; - gss_name_t src_name; + gss_name_t authn_name; + gss_name_t authz_name; pool_t pool; }; @@ -122,6 +131,28 @@ return major_status; } +static gss_name_t +import_name(struct auth_request *request, void *str, size_t len) +{ + OM_uint32 major_status, minor_status; + gss_buffer_desc name_buf; + gss_name_t name; + + name_buf.value=str; + name_buf.length=len; + 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; +} + static void gssapi_sec_context(struct gssapi_auth_request *request, gss_buffer_desc inbuf) { @@ -134,7 +165,7 @@ request->service_cred, &inbuf, GSS_C_NO_CHANNEL_BINDINGS, - &request->src_name, + &request->authn_name, NULL, /* mech_type */ &outbuf, NULL, /* ret_flags */ @@ -177,7 +208,9 @@ /* The clients return data should be empty here */ - ret[0] = 0x01; /* Only authentication, no integrity or confidentiality protection (yet?) */ + /* Only authentication, no integrity or confidentiality protection (yet?) */ + ret[0] = (SASL_GSSAPI_QOP_UNSPECIFIED| + SASL_GSSAPI_QOP_AUTH_ONLY); ret[1] = 0xFF; ret[2] = 0xFF; ret[3] = 0xFF; @@ -215,6 +248,7 @@ { OM_uint32 major_status, minor_status; gss_buffer_desc outbuf; + int equal_authn_authz=0; major_status = gss_unwrap(&minor_status, request->gss_ctx, &inbuf, &outbuf, NULL, NULL); @@ -233,6 +267,27 @@ return; } + 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; + } + major_status = gss_compare_name(&minor_status, + request->authn_name, + request->authz_name, + &equal_authn_authz); + if (equal_authn_authz == 0) { + auth_request_log_error(&request->auth_request, "gssapi", + "authn_name and authz_name differ: not supported"); + auth_request_fail(&request->auth_request); + return; + } + request->auth_request.user = p_strndup(request->auth_request.pool, ((unsigned char*) outbuf.value)+4, outbuf.length-4); @@ -272,7 +327,8 @@ auth_request_internal_failure(request); return; } - gssapi_request->src_name = GSS_C_NO_NAME; + gssapi_request->authn_name = GSS_C_NO_NAME; + gssapi_request->authz_name = GSS_C_NO_NAME; gssapi_request->sasl_gssapi_state = GSS_STATE_SEC_CONTEXT; @@ -299,6 +355,8 @@ GSS_C_NO_BUFFER); major_status = gss_release_cred(&minor_status, &gssapi_request->service_cred); + major_status = gss_release_name(&minor_status, &gssapi_request->authn_name); + major_status = gss_release_name(&minor_status, &gssapi_request->authz_name); pool_unref(request->pool); }