From c2655c2b98253e03c42eeeee1e5c60fe7107c5a4 Mon Sep 17 00:00:00 2001 From: Ken Hornstein Date: Tue, 24 Oct 2017 14:47:19 -0400 Subject: [PATCH] Add context information to SASL callback. Provide an extra context argument for the SASL negotiation callback that application code can use to pass down information that the callback might need. --- h/netsec.h | 8 ++++++-- mts/smtp/smtp.c | 9 +++++---- sbr/netsec.c | 34 ++++++++++++++++++++++------------ uip/popsbr.c | 7 ++++--- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/h/netsec.h b/h/netsec.h index 0a14a1d0..b115ed7c 100644 --- a/h/netsec.h +++ b/h/netsec.h @@ -258,6 +258,7 @@ enum sasl_message_type { * indatasize - The size of the input data in bytes * outdata - Output data (freed by caller) * outdatasize - Size of output data + * context - Extra context information potentially required by callback * errstr - An error string to be returned (freed by caller). * * As a general note, plugins should perform their own I/O. Buffers returned @@ -298,7 +299,8 @@ typedef int (*netsec_sasl_callback)(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatasize, unsigned char **outdata, - unsigned int *outdatasize, char **errstr); + unsigned int *outdatasize, + void *context, char **errstr); /* * Sets the SASL parameters for this connection. If this function is @@ -315,6 +317,7 @@ typedef int (*netsec_sasl_callback)(enum sasl_message_type mtype, * mechanism - The mechanism desired by the user. If NULL, the SASL * library will attempt to negotiate the best mechanism. * callback - SASL protocol callbacks + * context - Extra context information passed to the protocol callback * errstr - Error string. * * Returns NOTOK if SASL is not supported. @@ -322,7 +325,8 @@ typedef int (*netsec_sasl_callback)(enum sasl_message_type mtype, int netsec_set_sasl_params(netsec_context *ns_context, const char *service, const char *mechanism, - netsec_sasl_callback callback, char **errstr); + netsec_sasl_callback callback, + void *context, char **errstr); /* * Start SASL negotiation. The Netsec library will use the callbacks diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c index c7d95073..cc4a27cb 100644 --- a/mts/smtp/smtp.c +++ b/mts/smtp/smtp.c @@ -68,7 +68,7 @@ static int smhear (void); static char *EHLOset (char *) PURE; static int sm_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, - char **); + void *, char **); int sm_init (char *client, char *server, char *port, int watch, int verbose, @@ -133,7 +133,7 @@ smtp_init (char *client, char *server, char *port, int watch, int verbose, if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, - &errstr) != OK) + NULL, &errstr) != OK) return sm_nerror(errstr); } @@ -295,7 +295,7 @@ sendmail_init (char *client, int watch, int verbose, int debug, int sasl, if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, - &errstr) != OK) + NULL, &errstr) != OK) return sm_nerror(errstr); } @@ -947,11 +947,12 @@ EHLOset (char *s) static int sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, - unsigned int *outdatalen, char **errstr) + unsigned int *outdatalen, void *context, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len; + NMH_UNUSED(context); switch (mtype) { case NETSEC_SASL_START: diff --git a/sbr/netsec.c b/sbr/netsec.c index a0b11d37..537df825 100644 --- a/sbr/netsec.c +++ b/sbr/netsec.c @@ -74,6 +74,7 @@ struct _netsec_context { char *sasl_mech; /* User-requested mechanism */ char *sasl_chosen_mech; /* Mechanism chosen by SASL */ netsec_sasl_callback sasl_proto_cb; /* SASL callback we use */ + void *sasl_proto_context; /* Context to be used by SASL callback */ #ifdef OAUTH_SUPPORT char *oauth_service; /* OAuth2 service name */ #endif /* OAUTH_SUPPORT */ @@ -161,6 +162,7 @@ netsec_init(void) nsc->sasl_mech = NULL; nsc->sasl_chosen_mech = NULL; nsc->sasl_proto_cb = NULL; + nsc->sasl_proto_context = NULL; #ifdef OAUTH_SUPPORT nsc->oauth_service = NULL; #endif /* OAUTH_SUPPORT */ @@ -951,7 +953,7 @@ netsec_flush(netsec_context *nsc, char **errstr) int netsec_set_sasl_params(netsec_context *nsc, const char *service, const char *mechanism, netsec_sasl_callback callback, - char **errstr) + void *context, char **errstr) { #ifdef CYRUS_SASL sasl_callback_t *sasl_cbs; @@ -1029,6 +1031,7 @@ netsec_set_sasl_params(netsec_context *nsc, const char *service, } nsc->sasl_proto_cb = callback; + nsc->sasl_proto_context = context; return OK; } @@ -1173,7 +1176,8 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) } rc = nsc->sasl_proto_cb(NETSEC_SASL_START, xoauth_client_res, - xoauth_client_res_len, NULL, 0, errstr); + xoauth_client_res_len, NULL, 0, + nsc->sasl_proto_context, errstr); free(xoauth_client_res); if (rc != OK) @@ -1186,7 +1190,8 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) * error. */ - rc = nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, errstr); + rc = nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, + nsc->sasl_proto_context, errstr); if (rc != OK) { /* @@ -1196,9 +1201,10 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) * NOT get a success message at this point. */ free(*errstr); - nsc->sasl_proto_cb(NETSEC_SASL_WRITE, NULL, 0, NULL, 0, NULL); + nsc->sasl_proto_cb(NETSEC_SASL_WRITE, NULL, 0, NULL, 0, + nsc->sasl_proto_context, NULL); rc = nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, - errstr); + nsc->sasl_proto_context, errstr); if (rc == 0) { netsec_err(errstr, "Unexpected success after OAuth failure!"); } @@ -1256,7 +1262,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) nsc->sasl_chosen_mech = getcpy(chosen_mech); if (nsc->sasl_proto_cb(NETSEC_SASL_START, saslbuf, saslbuflen, NULL, 0, - errstr) != OK) + nsc->sasl_proto_context, errstr) != OK) return NOTOK; /* @@ -1270,8 +1276,9 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) */ if (nsc->sasl_proto_cb(NETSEC_SASL_READ, NULL, 0, &outbuf, &outbuflen, - errstr) != OK) { - nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); + nsc->sasl_proto_context, errstr) != OK) { + nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, + nsc->sasl_proto_context, NULL); return NOTOK; } @@ -1283,13 +1290,16 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) if (rc != SASL_OK && rc != SASL_CONTINUE) { netsec_err(errstr, "SASL client negotiation failed: %s", sasl_errdetail(nsc->sasl_conn)); - nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); + nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, + nsc->sasl_proto_context, NULL); return NOTOK; } if (nsc->sasl_proto_cb(NETSEC_SASL_WRITE, saslbuf, saslbuflen, - NULL, 0, errstr) != OK) { - nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); + NULL, 0, nsc->sasl_proto_context, + errstr) != OK) { + nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, + nsc->sasl_proto_context, NULL); return NOTOK; } } @@ -1300,7 +1310,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) */ if (nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, - errstr) != OK) { + nsc->sasl_proto_context, errstr) != OK) { /* * At this point we can't really send an abort since the SASL dialog * has completed, so just bubble back up the error message. diff --git a/uip/popsbr.c b/uip/popsbr.c index d79c8b3d..a9e442ba 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -34,7 +34,7 @@ static int vcommand(const char *, va_list) CHECK_PRINTF(1, 0); static int pop_getline (char *, int, netsec_context *); static int pop_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, - char **); + void *, char **); static int check_mech(char *server_mechs, size_t server_mechs_size) @@ -223,7 +223,7 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, if (sasl) { if (netsec_set_sasl_params(nsc, "pop", mech, pop_sasl_callback, - &errstr) != OK) { + NULL, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; @@ -292,11 +292,12 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, static int pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, - unsigned int *outdatalen, char **errstr) + unsigned int *outdatalen, void *context, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len, b64len; + NMH_UNUSED(context); switch (mtype) { case NETSEC_SASL_START: -- 2.56.0