cleanups to minimise merging hassle
[cyrus-sasl.git] / lib / client.c
index 1ba3874..ad11171 100644 (file)
@@ -402,11 +402,11 @@ _mech_plus_p(const char *mech, size_t len)
  */
 static int
 _sasl_client_order_mechs(const sasl_utils_t *utils,
-                         const char *mechs,
-                         int has_cb_data,
-                         char **ordered_mechs,
-                         size_t *count,
-                         int *server_can_cb)
+                        const char *mechs,
+                        int has_cb_data,
+                        char **ordered_mechs,
+                        size_t *count,
+                        int *server_can_cb)
 {
     char *list, *listp;
     size_t i;
@@ -417,31 +417,31 @@ _sasl_client_order_mechs(const sasl_utils_t *utils,
 
     listp = list = utils->malloc(strlen(mechs) + 1);
     if (list == NULL)
-        return SASL_NOMEM;
+       return SASL_NOMEM;
 
     do {
-        for (start = p = mechs, i = 0; *p != '\0'; p++) {
-            if (isspace(*p) || p[1] == '\0') {
-                size_t len = p - start;
-
-                if (p[1] == '\0')
-                    len++;
-
-                if (_mech_plus_p(start, len) == has_cb_data) {
-                    memcpy(listp, start, len);
-                    listp[len] = '\0';
-                    listp += len + 1;
-                    (*count)++;
-                    if (*server_can_cb == 0 && has_cb_data)
-                        *server_can_cb = 1;
-                }
-                start = p + 1;
-            }
-        }
-        if (has_cb_data)
-            has_cb_data = 0;
-        else
-            break;
+       for (start = p = mechs, i = 0; *p != '\0'; p++) {
+           if (isspace(*p) || p[1] == '\0') {
+               size_t len = p - start;
+
+               if (p[1] == '\0')
+                   len++;
+
+               if (_mech_plus_p(start, len) == has_cb_data) {
+                   memcpy(listp, start, len);
+                   listp[len] = '\0';
+                   listp += len + 1;
+                   (*count)++;
+                   if (*server_can_cb == 0 && has_cb_data)
+                       *server_can_cb = 1;
+               }
+               start = p + 1;
+           }
+       }
+       if (has_cb_data)
+           has_cb_data = 0;
+       else
+           break;
     } while (1);
 
     *listp = '\0';
@@ -486,6 +486,7 @@ int sasl_client_start(sasl_conn_t *conn,
     size_t i, list_len;
     sasl_ssf_t bestssf = 0, minssf = 0;
     int result, server_can_cb = 0;
+    unsigned int cbindingdisp = 0;
 
     if(_sasl_client_active==0) return SASL_NOTINIT;
 
@@ -511,27 +512,32 @@ int sasl_client_start(sasl_conn_t *conn,
     }
 
     result = _sasl_client_order_mechs(c_conn->cparams->utils,
-                                      mechlist,
-                                      SASL_CB_PRESENT(c_conn->cparams),
-                                      &ordered_mechs,
-                                      &list_len,
-                                      &server_can_cb);
+                                     mechlist,
+                                     SASL_CB_PRESENT(c_conn->cparams),
+                                     &ordered_mechs,
+                                     &list_len,
+                                     &server_can_cb);
     if (result != 0)
-        return result;
+       goto done;
 
-    /* If we have CB and the server supports it, we should use it */
-    if (SASL_CB_PRESENT(c_conn->cparams) && server_can_cb)
-        c_conn->cparams->chanbindingflag = SASL_CB_FLAG_WANT;
-    else
-        c_conn->cparams->chanbindingflag = SASL_CB_FLAG_NONE;
+    if (SASL_CB_PRESENT(c_conn->cparams)) {
+       if (server_can_cb == 0 && SASL_CB_CRITICAL(c_conn->cparams)) {
+           result = SASL_NOMECH;
+           goto done;
+       } else {
+           cbindingdisp = SASL_CB_DISP_WANT;
+       }
+    } else {
+       cbindingdisp = SASL_CB_DISP_NONE;
+    }
 
     for (i = 0, name = ordered_mechs; i < list_len; i++) {
        /* foreach in client list */
        for (m = cmechlist->mech_list; m != NULL; m = m->next) {
            int myflags, plus;
 
-            if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus))
-                continue;
+           if (!_sasl_is_equal_mech(name, m->m.plug->mech_name, &plus))
+               continue;
 
            /* Do we have the prompts for it? */
            if (!have_prompts(conn, m->m.plug))
@@ -555,6 +561,11 @@ int sasl_client_start(sasl_conn_t *conn,
            }
 
            /* Can we meet it's features? */
+          if (SASL_CB_PRESENT(c_conn->cparams) &&
+               !(m->m.plug->features & SASL_FEAT_CHANNEL_BINDING)) {
+               break;
+           }
+
            if ((m->m.plug->features & SASL_FEAT_NEEDSERVERFQDN)
                && !conn->serverFQDN) {
                break;
@@ -604,9 +615,10 @@ int sasl_client_start(sasl_conn_t *conn,
                break;
            }
 
-            /* Prefer server advertised CB mechanisms */
-            if (SASL_CB_PRESENT(c_conn->cparams) && plus)
-                c_conn->cparams->chanbindingflag = SASL_CB_FLAG_USED;
+           /* Prefer server advertised CB mechanisms */
+           if (SASL_CB_PRESENT(c_conn->cparams) && plus) {
+               cbindingdisp = SASL_CB_DISP_USED;
+           }
 
            if (mech) {
                *mech = m->m.plug->mech_name;
@@ -615,7 +627,7 @@ int sasl_client_start(sasl_conn_t *conn,
            bestm = m;
            break;
        }
-        name += strlen(name) + 1;
+       name += strlen(name) + 1;
     }
 
     if (bestm == NULL) {
@@ -638,6 +650,7 @@ int sasl_client_start(sasl_conn_t *conn,
 
     c_conn->cparams->external_ssf = conn->external.ssf;
     c_conn->cparams->props = conn->props;
+    c_conn->cparams->cbindingdisp = cbindingdisp;
     c_conn->mech = bestm;
 
     /* init that plugin */
@@ -663,7 +676,7 @@ int sasl_client_start(sasl_conn_t *conn,
 
  done:
     if (ordered_mechs != NULL)
-        c_conn->cparams->utils->free(ordered_mechs);
+       c_conn->cparams->utils->free(ordered_mechs);
     RETURN(conn, result);
 }