+ if (cfg->basic_mechs) {
+ allowed_mechs = cfg->basic_mechs;
+ } else if (cfg->allowed_mechs) {
+ allowed_mechs = cfg->allowed_mechs;
+ } else {
+ /* Try to fetch the default set if not explicitly configured,
+ * We need to do this because gss_acquire_cred_with_password()
+ * is currently limited to acquire creds for a single "default"
+ * mechanism if no desired mechanisms are passed in. This causes
+ * authentication to fail for secondary mechanisms as no user
+ * credentials are generated for those. */
+ maj = gss_indicate_mechs(&min, &indicated_mechs);
+ if (maj != GSS_S_COMPLETE) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, "%s",
+ mag_error(req, "gss_indicate_mechs() failed",
+ maj, min));
+ /* if indicated _mechs failed, set GSS_C_NO_OID_SET. This
+ * generally causes only the krb5 mechanism to be tried due
+ * to implementation constraints, but may change in future. */
+ allowed_mechs = GSS_C_NO_OID_SET;
+ } else {
+ allowed_mechs = indicated_mechs;
+ }
+ }
+
+ /* Remove Spnego if present, or we'd repeat failed authentiations
+ * multiple times, one within Spnego and then again with an explicit
+ * mechanism. We would normally just force Spnego and use
+ * gss_set_neg_mechs, but due to the way we source the server name
+ * and the fact MIT up to 1.14 at least does no handle union names,
+ * we can't provide spnego with a server name that can be used by
+ * multiple mechanisms, causing any but the first mechanism to fail.
+ * Also remove unwanted krb mechs, or AS requests will be repeated
+ * multiple times uselessly.
+ */
+ filtered_mechs = mag_filter_unwanted_mechs(allowed_mechs);
+ if (filtered_mechs == GSS_C_NO_OID_SET) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, req, "Fatal "
+ "failure while filtering mechs, aborting");
+ goto done;
+ } else if (filtered_mechs != allowed_mechs) {
+ /* if indicated_mechs where sourced then free them here before
+ * reusing the pointer */
+ gss_release_oid_set(&min, &indicated_mechs);
+
+ /* mark the list of mechs needs to be freed */
+ indicated_mechs = filtered_mechs;
+
+ /* use the filtered list */
+ allowed_mechs = filtered_mechs;