From: Ken Hornstein Date: Wed, 21 Sep 2016 04:06:52 +0000 (-0400) Subject: Add support for a base64-decoding snoop callback. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/567c0ca977b29670af9c2b66d221d03ce844c6f1?ds=inline;hp=-c Add support for a base64-decoding snoop callback. --- 567c0ca977b29670af9c2b66d221d03ce844c6f1 diff --git a/h/netsec.h b/h/netsec.h index 27d29382..e652a6f4 100644 --- a/h/netsec.h +++ b/h/netsec.h @@ -83,10 +83,34 @@ void netsec_set_snoop(netsec_context *ns_context, int snoop); * ns_context - Network security context * string - String to output * len - Length of string + * context - "Extra" context information to be used by callback. */ -typedef void (*netsec_snoop_callback)(netsec_context *ns_context, - const char *string, size_t len); +typedef void (netsec_snoop_callback)(netsec_context *ns_context, + const char *string, size_t len, + void *context); + +/* + * Set the snoop callback function; will be used to handle protocol-specific + * messages. Set to NULL to disable. + * + * Arguments: + * + * ns_context - Network security context + * callback - Snoop callback + * context - Extra context information to be passed to callback. + */ + +void netsec_set_snoop_callback(netsec_context *ns_context, + netsec_snoop_callback *callback, void *context); + +/* + * A sample callback protocols can utilize; decode base64 tokens in the + * output. The context is a pointer to an int which contains an offset + * into the data to start decoding. + */ + +extern netsec_snoop_callback netsec_b64_snoop_decoder; /* * Set the read timeout for this connection. diff --git a/sbr/netsec.c b/sbr/netsec.c index 3fd31854..4d0d672f 100644 --- a/sbr/netsec.c +++ b/sbr/netsec.c @@ -57,7 +57,8 @@ struct _netsec_context { int ns_fd; /* Descriptor for network connection */ int ns_snoop; /* If true, display network data */ int ns_snoop_noend; /* If true, didn't get a CR/LF on last line */ - netsec_snoop_callback ns_snoop_cb; /* Snoop output callback */ + netsec_snoop_callback *ns_snoop_cb; /* Snoop output callback */ + void *ns_snoop_context; /* Context data for snoop function */ int ns_timeout; /* Network read timeout, in seconds */ char *ns_userid; /* Userid for authentication */ unsigned char *ns_inbuffer; /* Our read input buffer */ @@ -126,6 +127,7 @@ netsec_init(void) nsc->ns_snoop = 0; nsc->ns_snoop_noend = 0; nsc->ns_snoop_cb = NULL; + nsc->ns_snoop_context = NULL; nsc->ns_userid = NULL; nsc->ns_timeout = 60; /* Our default */ nsc->ns_inbufsize = NETSEC_BUFSIZE; @@ -258,6 +260,50 @@ netsec_set_snoop(netsec_context *nsc, int snoop) nsc->ns_snoop = snoop; } +/* + * Set the snoop callback for this connection. + */ + +void netsec_set_snoop_callback(netsec_context *nsc, + netsec_snoop_callback callback, void *context) +{ + nsc->ns_snoop_cb = callback; + nsc->ns_snoop_context = context; +} + +/* + * A base64-decoding snoop callback + */ + +void +netsec_b64_snoop_decoder(netsec_context *nsc, const char *string, size_t len, + void *context) +{ + const char *decoded; + size_t decodedlen; + + int offset = context ? *((int *) context) : 0; + + if (offset > 0) { + /* + * Output non-base64 data first. + */ + fprintf(stderr, "%.*s", offset, string); + string += offset; + len -= offset; + } + + if (decodeBase64(string, &decoded, &decodedlen, 1, NULL) == OK) { + char *hexified; + hexify((const unsigned char *) decoded, decodedlen, &hexified); + fprintf(stderr, "b64<%s>\n", hexified); + free(hexified); + free((char *) decoded); + } else { + fprintf(stderr, "%.*s\n", (int) len, string); + } +} + /* * Set the read timeout for this connection */ @@ -357,7 +403,8 @@ retry: #endif /* TLS_SUPPORT */ fprintf(stderr, "<= "); if (nsc->ns_snoop_cb) - nsc->ns_snoop_cb(nsc, sptr, strlen(sptr)); + nsc->ns_snoop_cb(nsc, sptr, strlen(sptr), + nsc->ns_snoop_context); else fprintf(stderr, "%s\n", sptr); } @@ -750,7 +797,8 @@ retry: #endif /* TLS_SUPPORT */ fprintf(stderr, "=> "); if (nsc->ns_snoop_cb) - nsc->ns_snoop_cb(nsc, nsc->ns_outptr, outlen); + nsc->ns_snoop_cb(nsc, nsc->ns_outptr, outlen, + nsc->ns_snoop_context); else fprintf(stderr, "%.*s\n", outlen, nsc->ns_outptr); } else { diff --git a/uip/popsbr.c b/uip/popsbr.c index 71011667..26f4fa0c 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -289,7 +289,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, unsigned int *outdatalen, char **errstr) { - int rc; + int rc, snoopoffset; char *mech, *line; size_t len, b64len; @@ -333,13 +333,18 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, "for initial challenge response"); return NOTOK; } + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); + netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; } else { + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, + &snoopoffset); + snoopoffset = 6 + strlen(mech); rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data); free(b64data); @@ -362,7 +367,10 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, * and feed it back into the SASL library. */ case NETSEC_SASL_READ: + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); + snoopoffset = 2; line = netsec_readline(nsc, &len, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); if (line == NULL) return NOTOK; @@ -393,7 +401,9 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, b64data); + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); + netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); } @@ -438,8 +448,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, return NOTOK; break; } - - return OK; +return OK; } /*