From c3ef0663e190e058bb434ff3f5faea103f3f448b Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 27 Sep 2010 00:41:50 +0200 Subject: [PATCH] move more CB selection logic to libsasl --- include/sasl.h | 6 +++--- include/saslplug.h | 20 ++++++++++---------- lib/auxprop.c | 1 + lib/client.c | 51 +++++++++++++++++++++++---------------------------- lib/common.c | 38 +++++++++++++++++++++++++++----------- lib/saslint.h | 4 ++++ lib/server.c | 37 +++++++++++++++++++++++++++++-------- sample/client.c | 22 ++++++++++++++-------- sample/server.c | 6 +++--- 9 files changed, 114 insertions(+), 71 deletions(-) diff --git a/include/sasl.h b/include/sasl.h index 714f0ca..b082057 100755 --- a/include/sasl.h +++ b/include/sasl.h @@ -791,14 +791,14 @@ LIBSASL_API int sasl_getprop(sasl_conn_t *conn, int propnum, * is particularly useful for servers that respond to multiple names. */ #define SASL_GSS_LOCAL_NAME 20 -typedef struct sasl_channel_bindings { +typedef struct sasl_channel_binding { char *type; int critical; unsigned long len; unsigned char *data; -} sasl_channel_bindings; +} sasl_channel_binding; -#define SASL_CHANNEL_BINDINGS 21 +#define SASL_CHANNEL_BINDING 21 /* set property in SASL connection state * returns: diff --git a/include/saslplug.h b/include/saslplug.h index 321e79f..ea5368e 100755 --- a/include/saslplug.h +++ b/include/saslplug.h @@ -255,8 +255,8 @@ typedef struct sasl_client_params { /* for additions which don't require a version upgrade; set to 0 */ void *gss_creds; - void *chanbindingstype; - void *chanbindingsdata; + void *chanbindingtype; + void *chanbindingdata; void *spare_ptr4; /* Canonicalize a user name from on-wire to internal format @@ -292,9 +292,9 @@ typedef struct sasl_client_params { #define SASL_CB_FLAG_NONE 0 /* client did not support CB */ #define SASL_CB_FLAG_USED 1 /* client supports and used CB */ #define SASL_CB_FLAG_WANT 2 /* client supports CB, thinks server does not */ - - int chanbindingsflag; - int chanbindingslen; + int chanbindingflag; +#define SASL_CB_PRESENT(params) ((params)->chanbindingtype != NULL && (params)->chanbindinglen) + int chanbindinglen; int spare_int3; /* flags field as passed to sasl_client_new */ @@ -337,7 +337,7 @@ typedef struct sasl_client_params { #define SASL_FEAT_GSS_FRAMING 0x0040 /* Underlying mechanism supports channel binding */ -#define SASL_FEAT_CHANNEL_BINDINGS 0x0080 +#define SASL_FEAT_CHANNEL_BINDING 0x0080 /* client plug-in features */ #define SASL_FEAT_NEEDSERVERFQDN 0x0001 @@ -561,13 +561,13 @@ typedef struct sasl_server_params { /* for additions which don't require a version upgrade; set to 0 */ void *gss_creds; - void *chanbindingstype; - void *chanbindingsdata; + void *chanbindingtype; + void *chanbindingdata; void *spare_ptr4; int (*spare_fptr1)(); int (*spare_fptr2)(); - int chanbindingscrit; - int chanbindingslen; + int chanbindingcrit; + int chanbindinglen; int spare_int3; /* flags field as passed to sasl_server_new */ diff --git a/lib/auxprop.c b/lib/auxprop.c index a3f54c0..1be6c2a 100644 --- a/lib/auxprop.c +++ b/lib/auxprop.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "saslint.h" struct proppool diff --git a/lib/client.c b/lib/client.c index c42d6f5..4c35519 100644 --- a/lib/client.c +++ b/lib/client.c @@ -390,19 +390,6 @@ static int have_prompts(sasl_conn_t *conn, return 1; /* we have all the prompts */ } -static inline int sasl_is_plus_mech(const char *mech) -{ - size_t len = strlen(mech); - const char *p; - - if (len < 5) - return 0; - - p = &mech[len - 5]; - - return (strcmp(p, "-PLUS") == 0); -} - /* select a mechanism for a connection * mechlist -- mechanisms server has available (punctuation ignored) * secret -- optional secret from previous session @@ -464,6 +451,8 @@ int sasl_client_start(sasl_conn_t *conn, minssf = conn->props.min_ssf - conn->external.ssf; } + c_conn->cparams->chanbindingflag = SASL_CB_FLAG_NONE; + /* parse mechlist */ list_len = strlen(mechlist); @@ -491,11 +480,10 @@ int sasl_client_start(sasl_conn_t *conn, /* foreach in client list */ for (m = cmechlist->mech_list; m != NULL; m = m->next) { - int myflags; - - /* Is this the mechanism the server is suggesting? */ - if (strcasecmp(m->m.plug->mech_name, name)) - continue; /* no */ + int myflags, plus; + + 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)) @@ -530,16 +518,6 @@ int sasl_client_start(sasl_conn_t *conn, break; } - /* If client requires channel binding, prefer -PLUS mech */ - if (c_conn->cparams->chanbindingslen != 0) { - if (sasl_is_plus_mech(name)) - c_conn->cparams->chanbindingsflag = SASL_CB_FLAG_USED; - else - c_conn->cparams->chanbindingsflag = SASL_CB_FLAG_WANT; - } else { - c_conn->cparams->chanbindingsflag = SASL_CB_FLAG_NONE; - } - #ifdef PREFER_MECH if (strcasecmp(m->m.plug->mech_name, PREFER_MECH) && bestm && m->m.plug->max_ssf <= bestssf) { @@ -578,6 +556,13 @@ int sasl_client_start(sasl_conn_t *conn, break; } + if (SASL_CB_PRESENT(c_conn->cparams)) { + if (plus) + c_conn->cparams->chanbindingflag = SASL_CB_FLAG_USED; + else + c_conn->cparams->chanbindingflag = SASL_CB_FLAG_WANT; + } + if (mech) { *mech = m->m.plug->mech_name; } @@ -967,6 +952,16 @@ _sasl_print_mechanism ( printf ("%cNEED_SERVER_FQDN", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_GSS_FRAMING) { + printf ("%cGSS_FRAMING", delimiter); + delimiter = '|'; + } + + if (m->plug->features & SASL_FEAT_CHANNEL_BINDING) { + printf ("%cCHANNEL_BINDING", delimiter); + delimiter = '|'; + } } /* Delay loading is not supported for the client side plugins: diff --git a/lib/common.c b/lib/common.c index 1bf804d..9a8e8ce 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1208,20 +1208,18 @@ int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value) else ((sasl_client_conn_t *)conn)->cparams->gss_creds = (void *)value; break; - case SASL_CHANNEL_BINDINGS: { - struct sasl_channel_bindings *cb = (struct sasl_channel_bindings *)value; + case SASL_CHANNEL_BINDING: { + struct sasl_channel_binding *cb = (struct sasl_channel_binding *)value; if (conn->type == SASL_CONN_SERVER) { - int cb_flag; - - ((sasl_server_conn_t *)conn)->sparams->chanbindingstype = cb->type; - ((sasl_server_conn_t *)conn)->sparams->chanbindingscrit = cb->critical; - ((sasl_server_conn_t *)conn)->sparams->chanbindingsdata = cb->data; - ((sasl_server_conn_t *)conn)->sparams->chanbindingslen = cb->len; + ((sasl_server_conn_t *)conn)->sparams->chanbindingtype = cb->type; + ((sasl_server_conn_t *)conn)->sparams->chanbindingcrit = cb->critical; + ((sasl_server_conn_t *)conn)->sparams->chanbindingdata = cb->data; + ((sasl_server_conn_t *)conn)->sparams->chanbindinglen = cb->len; } else { - ((sasl_client_conn_t *)conn)->cparams->chanbindingstype = cb->type; - ((sasl_client_conn_t *)conn)->cparams->chanbindingsdata = cb->data; - ((sasl_client_conn_t *)conn)->cparams->chanbindingslen = cb->len; + ((sasl_client_conn_t *)conn)->cparams->chanbindingtype = cb->type; + ((sasl_client_conn_t *)conn)->cparams->chanbindingdata = cb->data; + ((sasl_client_conn_t *)conn)->cparams->chanbindinglen = cb->len; } break; } @@ -2333,6 +2331,24 @@ int sasl_listmech(sasl_conn_t *conn, PARAMERROR(conn); } +int _sasl_is_equal_mech(const char *req_mech, + const char *plug_mech, + int *plus) +{ + size_t len = strlen(req_mech); + size_t n; + + if (len > 5 && + strcasecmp(&req_mech[len - 5], "-PLUS") == 0) { + n = len - 5; + *plus = 1; + } else { + n = len; + *plus = 0; + } + + return (strncasecmp(req_mech, plug_mech, n) == 0); +} #ifndef WIN32 static char * diff --git a/lib/saslint.h b/lib/saslint.h index b1c20ef..1af2415 100644 --- a/lib/saslint.h +++ b/lib/saslint.h @@ -301,6 +301,10 @@ extern int (*_sasl_server_cleanup_hook)(void); extern sasl_allocation_utils_t _sasl_allocation_utils; extern sasl_mutex_utils_t _sasl_mutex_utils; +extern int _sasl_is_equal_mech(const char *req_mech, + const char *plug_mech, + int *plus); + /* * checkpw.c */ diff --git a/lib/server.c b/lib/server.c index 1533c10..3013019 100644 --- a/lib/server.c +++ b/lib/server.c @@ -1214,6 +1214,7 @@ int sasl_server_start(sasl_conn_t *conn, int result; context_list_t *cur, **prev; mechanism_t *m; + int plus = 0; if (_sasl_server_active==0) return SASL_NOTINIT; @@ -1230,13 +1231,11 @@ int sasl_server_start(sasl_conn_t *conn, if(serverout) *serverout = NULL; if(serveroutlen) *serveroutlen = 0; - while (m!=NULL) - { - if ( strcasecmp(mech, m->m.plug->mech_name)==0) - { + while (m != NULL) { + if (_sasl_is_equal_mech(mech, m->m.plug->mech_name, &plus)) break; - } - m=m->next; + + m = m->next; } if (m==NULL) { @@ -1511,6 +1510,7 @@ int _sasl_server_listmech(sasl_conn_t *conn, size_t resultlen; int flag; const char *mysep; + sasl_server_conn_t *s_conn = (sasl_server_conn_t *) conn; /* cast */ /* if there hasn't been a sasl_sever_init() fail */ if (_sasl_server_active==0) return SASL_NOTINIT; @@ -1535,8 +1535,9 @@ int _sasl_server_listmech(sasl_conn_t *conn, INTERROR(conn, SASL_NOMECH); resultlen = (prefix ? strlen(prefix) : 0) - + (strlen(mysep) * (mechlist->mech_length - 1)) - + mech_names_len() + + (strlen(mysep) * (mechlist->mech_length - 1) * 2) + + (mech_names_len() * 2) /* including -PLUS variant */ + + (mechlist->mech_length * (sizeof("-PLUS") - 1)) + (suffix ? strlen(suffix) : 0) + 1; ret = _buf_alloc(&conn->mechlist_buf, @@ -1567,6 +1568,16 @@ int _sasl_server_listmech(sasl_conn_t *conn, /* now print the mechanism name */ strcat(conn->mechlist_buf, listptr->m.plug->mech_name); + + /* advertise -PLUS variant if mechanism and application support CB */ + if ((listptr->m.plug->features & SASL_FEAT_CHANNEL_BINDING) && + SASL_CB_PRESENT(s_conn->sparams)) { + if (pcount != NULL) + (*pcount)++; + strcat(conn->mechlist_buf, mysep); + strcat(conn->mechlist_buf, listptr->m.plug->mech_name); + strcat(conn->mechlist_buf, "-PLUS"); + } } listptr = listptr->next; @@ -2046,6 +2057,16 @@ _sasl_print_mechanism ( printf ("%cNEED_GETSECRET", delimiter); delimiter = '|'; } + + if (m->plug->features & SASL_FEAT_GSS_FRAMING) { + printf ("%cGSS_FRAMING", delimiter); + delimiter = '|'; + } + + if (m->plug->features & SASL_FEAT_CHANNEL_BINDING) { + printf ("%cCHANNEL_BINDING", delimiter); + delimiter = '|'; + } } if (m->f) { diff --git a/sample/client.c b/sample/client.c index d1b02d4..ec0514f 100644 --- a/sample/client.c +++ b/sample/client.c @@ -321,7 +321,7 @@ int mysasl_negotiate(FILE *in, FILE *out, sasl_conn_t *conn) void usage(void) { - fprintf(stderr, "usage: client [-p port] [-s service] [-m mech] host\n"); + fprintf(stderr, "usage: client [-c] [-p port] [-s service] [-m mech] host\n"); exit(EX_USAGE); } @@ -341,10 +341,15 @@ int main(int argc, char *argv[]) int salen; int niflags, error; struct sockaddr_storage local_ip, remote_ip; - sasl_channel_bindings cb; + int cb_flag = 0; + sasl_channel_binding cb; - while ((c = getopt(argc, argv, "p:s:m:")) != EOF) { + while ((c = getopt(argc, argv, "cp:s:m:")) != EOF) { switch(c) { + case 'c': + cb_flag = 1; + break; + case 'p': port = optarg; break; @@ -420,12 +425,13 @@ int main(int argc, char *argv[]) r = sasl_client_new(service, host, localaddr, remoteaddr, NULL, 0, &conn); if (r != SASL_OK) saslfail(r, "allocating connection state"); - cb.type = "sasl-sample"; - cb.critical = 0; - cb.data = "this is a test of channel bindings"; - cb.len = strlen(cb.data); + if (cb_flag) { + cb.type = "sasl-sample"; + cb.data = "this is a test of channel binding"; + cb.len = strlen(cb.data); - sasl_setprop(conn, SASL_CHANNEL_BINDINGS, &cb); + sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); + } /* set external properties here sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops); */ diff --git a/sample/server.c b/sample/server.c index 0ba17a8..2b4f72d 100644 --- a/sample/server.c +++ b/sample/server.c @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) int nfds, fd = -1; FILE *in, *out; fd_set readfds; - sasl_channel_bindings cb; + sasl_channel_binding cb; FD_ZERO(&readfds); for (i = 1; i <= l[0]; i++) @@ -442,10 +442,10 @@ int main(int argc, char *argv[]) cb.type = "sasl-sample"; cb.critical = 0; - cb.data = "this is a test of channel bindings"; + cb.data = "this is a test of channel binding"; cb.len = strlen(cb.data); - sasl_setprop(conn, SASL_CHANNEL_BINDINGS, &cb); + sasl_setprop(conn, SASL_CHANNEL_BINDING, &cb); /* set external properties here sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops); */ -- 2.1.4