*/
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;
- const char *p, *start = NULL;
+ size_t i, mechslen, start;
*count = 0;
*server_can_cb = 0;
- listp = list = utils->malloc(strlen(mechs) + 1);
+ if (mechs == NULL || mechs[0] == '\0')
+ return SASL_NOMECH;
+
+ mechslen = strlen(mechs);
+
+ listp = list = utils->malloc(mechslen + 1);
if (list == NULL)
- return SASL_NOMEM;
+ return SASL_NOMEM;
+ /* xxx confirm this with rfc 2222
+ * SASL mechanism allowable characters are "AZaz-_"
+ * seperators can be any other characters and of any length
+ * even variable lengths between
+ *
+ * Apps should be encouraged to simply use space or comma space
+ * though
+ */
+#define ismechchar(c) (isalnum((c)) || (c) == '_' || (c) == '-')
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 (i = start = 0; i <= mechslen; i++) {
+ if (!ismechchar(mechs[i])) {
+ const char *mechp = &mechs[start];
+ size_t len = i - start;
+
+ if (len != 0 &&
+ _mech_plus_p(mechp, len) == has_cb_data) {
+ memcpy(listp, mechp, len);
+ listp[len] = '\0';
+ listp += len + 1;
+ (*count)++;
+ if (*server_can_cb == 0 && has_cb_data)
+ *server_can_cb = 1;
+ }
+ start = ++i;
+ }
+ }
+ if (has_cb_data)
+ has_cb_data = 0;
+ else
+ break;
} while (1);
- *listp = '\0';
*ordered_mechs = list;
return SASL_OK;
* SASL_INTERACT -- user interaction needed to fill in prompt_need list
*/
-/* xxx confirm this with rfc 2222
- * SASL mechanism allowable characters are "AZaz-_"
- * seperators can be any other characters and of any length
- * even variable lengths between
- *
- * Apps should be encouraged to simply use space or comma space
- * though
- */
int sasl_client_start(sasl_conn_t *conn,
const char *mechlist,
sasl_interact_t **prompt_need,
size_t i, list_len;
sasl_ssf_t bestssf = 0, minssf = 0;
int result, server_can_cb = 0;
+ unsigned int cbindingdisp;
if(_sasl_client_active==0) return SASL_NOTINIT;
}
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_BADBINDING;
+ 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))
}
/* Can we meet it's features? */
- if (SASL_CB_PRESENT(c_conn->cparams) &&
- !(m->m.plug->features & SASL_FEAT_CHANNEL_BINDING)) {
- break;
- }
+ 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;
}
- /* 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;
bestm = m;
break;
}
- name += strlen(name) + 1;
+ name += strlen(name) + 1;
}
if (bestm == NULL) {
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 */
done:
if (ordered_mechs != NULL)
- c_conn->cparams->utils->free(ordered_mechs);
+ c_conn->cparams->utils->free(ordered_mechs);
RETURN(conn, result);
}