X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=lib%2Fserver.c;h=928447d6f4ad6476de708528cfca245a4c451eb2;hb=5e40cd98eeeec5ade64ed83cc413591869be18a7;hp=301301954feb5c298fafce50870a17041d0054f4;hpb=c3ef0663e190e058bb434ff3f5faea103f3f448b;p=cyrus-sasl.git diff --git a/lib/server.c b/lib/server.c index 3013019..928447d 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1453,7 +1453,39 @@ int sasl_server_step(sasl_conn_t *conn, conn->oparams.maxoutbuf = conn->props.maxbufsize; } - if(conn->oparams.user == NULL || conn->oparams.authid == NULL) { + /* Validate channel bindings */ + switch (conn->oparams.cbindingdisp) { + case SASL_CB_DISP_NONE: + if (SASL_CB_CRITICAL(s_conn->sparams)) { + sasl_seterror(conn, 0, + "server requires channel binding but client provided none"); + ret = SASL_BADAUTH; + } + break; + case SASL_CB_DISP_WANT: + if (SASL_CB_PRESENT(s_conn->sparams)) { + sasl_seterror(conn, 0, + "client incorrectly assumed server had no channel binding"); + ret = SASL_BADAUTH; + } + break; + case SASL_CB_DISP_USED: + if (!SASL_CB_PRESENT(s_conn->sparams)) { + sasl_seterror(conn, 0, + "client provided channel binding but server had none"); + ret = SASL_BADAUTH; + } else if (strcmp(conn->oparams.cbindingname, + s_conn->sparams->cbinding->name) != 0) { + sasl_seterror(conn, 0, + "client channel binding %s does not match server %s", + conn->oparams.cbindingname, s_conn->sparams->cbinding->name); + ret = SASL_BADAUTH; + } + break; + } + + if (ret == SASL_OK && + (conn->oparams.user == NULL || conn->oparams.authid == NULL)) { sasl_seterror(conn, 0, "mech did not call canon_user for both authzid " \ "and authid"); @@ -1556,25 +1588,35 @@ int _sasl_server_listmech(sasl_conn_t *conn, for (lup = 0; lup < mechlist->mech_length; lup++) { /* currently, we don't use the "user" parameter for anything */ if (mech_permitted(conn, listptr) == SASL_OK) { - if (pcount != NULL) + /* + * If the server would never succeed in the authentication of + * he non-PLUS-variant due to policy reasons, it MUST advertise + * only the PLUS-variant. + */ + if (!SASL_CB_PRESENT(s_conn->sparams) || + !SASL_CB_CRITICAL(s_conn->sparams)) { + if (pcount != NULL) (*pcount)++; - - /* print separator */ - if (flag) { - strcat(conn->mechlist_buf, mysep); - } else { - flag = 1; - } - - /* now print the mechanism name */ - strcat(conn->mechlist_buf, listptr->m.plug->mech_name); - - /* advertise -PLUS variant if mechanism and application support CB */ + if (flag) + strcat(conn->mechlist_buf, mysep); + else + flag = 1; + strcat(conn->mechlist_buf, listptr->m.plug->mech_name); + } + /* + * If the server cannot support channel binding, it SHOULD + * advertise only the non-PLUS-variant. Here, supporting channel + * binding means the underlying SASL mechanism supports it and + * the application has set some channel binding data. + */ if ((listptr->m.plug->features & SASL_FEAT_CHANNEL_BINDING) && SASL_CB_PRESENT(s_conn->sparams)) { if (pcount != NULL) (*pcount)++; - strcat(conn->mechlist_buf, mysep); + if (flag) + strcat(conn->mechlist_buf, mysep); + else + flag = 1; strcat(conn->mechlist_buf, listptr->m.plug->mech_name); strcat(conn->mechlist_buf, "-PLUS"); }