GSS_S_PROMPTING_NEEDED is a bit
[cyrus-sasl.git] / plugins / gs2.c
index 9e29fe1..6faa70d 100644 (file)
 #define GS2_CB_FLAG_Y       0x02
 #define GS2_NONSTD_FLAG     0x10
 
+#ifndef GSS_S_PROMPTING_NEEDED
+#define GSS_S_PROMPTING_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 5))
+#endif
+
 typedef struct context {
     gss_ctx_id_t gss_ctx;
     gss_name_t client_name;
@@ -440,11 +444,6 @@ gs2_server_mech_step(void *conn_context,
 
     assert(maj_stat == GSS_S_COMPLETE);
 
-    if ((out_flags & GSS_C_SEQUENCE_FLAG) == 0)  {
-        ret = SASL_BADAUTH;
-        goto cleanup;
-    }
-
     maj_stat = gss_display_name(&min_stat, text->client_name,
                                 &name_buf, NULL);
     if (GSS_ERROR(maj_stat))
@@ -689,7 +688,7 @@ static int gs2_client_mech_step(void *conn_context,
     gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER;
     OM_uint32 maj_stat = GSS_S_FAILURE, min_stat = 0;
-    OM_uint32 req_flags, ret_flags;
+    OM_uint32 ret_flags;
     int ret = SASL_FAIL;
     int initialContextToken;
 
@@ -766,8 +765,6 @@ static int gs2_client_mech_step(void *conn_context,
             goto cleanup;
     }
 
-    req_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG;
-
     maj_stat = gss_init_sec_context(&min_stat,
                                     (params->gss_creds != GSS_C_NO_CREDENTIAL)
                                         ? (gss_cred_id_t)params->gss_creds
@@ -775,7 +772,7 @@ static int gs2_client_mech_step(void *conn_context,
                                     &text->gss_ctx,
                                     text->server_name,
                                     (gss_OID)text->mechanism,
-                                    req_flags,
+                                    GSS_C_MUTUAL_FLAG,
                                     GSS_C_INDEFINITE,
                                     &text->gss_cbindings,
                                     serverinlen ? &input_token : GSS_C_NO_BUFFER,
@@ -814,7 +811,8 @@ static int gs2_client_mech_step(void *conn_context,
     if (GSS_ERROR(maj_stat))
         goto cleanup;
 
-    if ((ret_flags & req_flags) != req_flags) {
+    if (params->cbindingdisp != SASL_CB_DISP_NONE &&
+        (ret_flags & GSS_C_MUTUAL_FLAG) == 0) {
         maj_stat = SASL_BADAUTH;
         goto cleanup;
     }
@@ -840,7 +838,7 @@ cleanup:
 
     if (ret == SASL_OK && maj_stat != GSS_S_COMPLETE) {
         sasl_gs2_seterror(text->utils, maj_stat, min_stat);
-        ret = SASL_FAIL;
+        ret = (maj_stat & GSS_S_PROMPTING_NEEDED) ? SASL_INTERACT : SASL_FAIL;
     }
     if (ret < SASL_OK)
         sasl_gs2_free_context_contents(text);
@@ -1285,7 +1283,7 @@ gs2_get_mech_attrs(const sasl_utils_t *utils,
     }
 
     *security_flags = SASL_SEC_NOPLAINTEXT | SASL_SEC_NOACTIVE;
-    *features = SASL_FEAT_WANT_CLIENT_FIRST | SASL_FEAT_CHANNEL_BINDING;
+    *features = SASL_FEAT_WANT_CLIENT_FIRST;
     if (prompts != NULL)
         *prompts = gs2_required_prompts;
 
@@ -1299,8 +1297,10 @@ gs2_get_mech_attrs(const sasl_utils_t *utils,
         *security_flags |= SASL_SEC_NOANONYMOUS;
     if (MA_PRESENT(GSS_C_MA_DELEG_CRED))
         *security_flags |= SASL_SEC_PASS_CREDENTIALS;
-    if (MA_PRESENT(GSS_C_MA_AUTH_TARG))
+    if (MA_PRESENT(GSS_C_MA_AUTH_TARG)) {
+        *features |= SASL_FEAT_CHANNEL_BINDING;
         *security_flags |= SASL_SEC_MUTUAL_AUTH;
+    }
     if (MA_PRESENT(GSS_C_MA_AUTH_INIT_INIT) && prompts != NULL)
         *prompts = NULL;
     if (MA_PRESENT(GSS_C_MA_ITOK_FRAMED))
@@ -1317,7 +1317,7 @@ gs2_get_mech_attrs(const sasl_utils_t *utils,
 static int gs2_indicate_mechs(const sasl_utils_t *utils)
 {
     OM_uint32 major, minor;
-    gss_OID_desc desired_oids[3];
+    gss_OID_desc desired_oids[2];
     gss_OID_set_desc desired_attrs;
     gss_OID_desc except_oids[3];
     gss_OID_set_desc except_attrs;
@@ -1326,8 +1326,7 @@ static int gs2_indicate_mechs(const sasl_utils_t *utils)
         return SASL_OK;
 
     desired_oids[0] = *GSS_C_MA_AUTH_INIT;
-    desired_oids[1] = *GSS_C_MA_AUTH_TARG;
-    desired_oids[2] = *GSS_C_MA_CBINDINGS;
+    desired_oids[1] = *GSS_C_MA_CBINDINGS;
     desired_attrs.count = sizeof(desired_oids)/sizeof(desired_oids[0]);
     desired_attrs.elements = desired_oids;
 
@@ -1709,7 +1708,7 @@ interact:
 cleanup:
     if (result == SASL_OK && maj_stat != GSS_S_COMPLETE) {
         sasl_gs2_seterror(text->utils, maj_stat, min_stat);
-        result = SASL_FAIL;
+        result = (maj_stat & GSS_S_PROMPTING_NEEDED) ? SASL_INTERACT : SASL_FAIL;
     }
 
     gss_release_buffer(&min_stat, &cred_authid);