X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/ceaab2f46ae8fa4598b9682eaf3210cda21517c9..94187a80bd60baab4b9c4b949ad820d730578123:/h/netsec.h diff --git a/h/netsec.h b/h/netsec.h index ef0d521d..3e7975b4 100644 --- a/h/netsec.h +++ b/h/netsec.h @@ -1,11 +1,9 @@ -/* - * Network security library routines for nmh. +/* netsec.h -- network-security library routines. * * These are a common set of routines to handle network security for * things like SASL and OpenSSL. */ -struct _netsec_context; typedef struct _netsec_context netsec_context; /* @@ -17,15 +15,15 @@ netsec_context *netsec_init(void); /* * Shuts down the security context for a connection and frees all - * associated resources. + * associated resources. Will unconditionally close the network socket + * as well. * * Arguments: * * ns_context - Network security context - * closeflag - If set to 1, close the socket descriptor as well. */ -void netsec_shutdown(netsec_context *ns_context, int closeflag); +void netsec_shutdown(netsec_context *ns_context); /* * Sets the file descriptor for this connection. This will be used by @@ -34,10 +32,11 @@ void netsec_shutdown(netsec_context *ns_context, int closeflag); * Arguments: * * ns_context - Network security context - * fd - File descriptor of network connection. + * readfd - Read file descriptor of remote connection. + * writefd - Write file descriptor of remote connection */ -void netsec_set_fd(netsec_context *ns_context, int fd); +void netsec_set_fd(netsec_context *ns_context, int readfd, int writefd); /* * Set the userid used to authenticate to this connection. @@ -50,6 +49,19 @@ void netsec_set_fd(netsec_context *ns_context, int fd); void netsec_set_userid(netsec_context *ns_context, const char *userid); +/* + * Set the hostname of the server we're connecting to. This is used + * by the Cyrus-SASL library and by the TLS code. This must be called + * before netsec_negotiate_tls() or netsec_set_sasl_params(). + * + * Arguments: + * + * ns_context - Network security context + * hostname - FQDN of remote host. Cannot be NULL. + */ + +void netsec_set_hostname(netsec_context *ns_context, const char *hostname); + /* * Returns "snoop" status on current connection. * @@ -60,7 +72,7 @@ void netsec_set_userid(netsec_context *ns_context, const char *userid); * Returns "1" if snoop is enabled, 0 if it is not. */ -int netsec_get_snoop(netsec_context *ns_context); +int netsec_get_snoop(netsec_context *ns_context) PURE; /* * Sets "snoop" status; if snoop is set to a nonzero value, network traffic @@ -74,6 +86,44 @@ int netsec_get_snoop(netsec_context *ns_context); void netsec_set_snoop(netsec_context *ns_context, int snoop); +/* + * A callback designed to handle the snoop output; it can be used by + * a protocol to massage the data in a more user-friendly way. + * + * Arguments: + * + * 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, + 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. * @@ -100,7 +150,7 @@ void netsec_set_timeout(netsec_context *ns_context, int timeout); * Returns pointer to string, or NULL on error. */ -char *netsec_readline(netsec_context *ns_context, size_t *lenght, +char *netsec_readline(netsec_context *ns_context, size_t *length, char **errstr); /* @@ -151,7 +201,7 @@ int netsec_write(netsec_context *ns_context, const void *buffer, size_t size, */ int netsec_printf(netsec_context *ns_context, char **errstr, - const char *format, ...); + const char *format, ...) CHECK_PRINTF(3, 4); /* * Write bytes using a va_list argument. @@ -167,7 +217,7 @@ int netsec_printf(netsec_context *ns_context, char **errstr, */ int netsec_vprintf(netsec_context *ns_context, char **errstr, - const char *format, va_list ap); + const char *format, va_list ap) CHECK_PRINTF(3, 0); /* * Flush any buffered bytes to the network. @@ -208,18 +258,20 @@ 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 + * by NETSEC_SASL_READ should be allocated by the plugins and will be freed + * by the netsec package. Error messages returned should be created by + * netsec_err(). + * * Parameter interpretation based on mtype value: * * NETSEC_SASL_START - Create a protocol message that starts SASL * authentication. If an initial response is * supported, indata and indatasize will contain it. * Otherwise they will be set to NULL and 0. - * The complete protocol message should be - * stored in outdata/outdatasize, to be free()d - * by the caller. Alternatively, the plugin - * can choose to send the data on their own. * NETSEC_SASL_READ - Parse and decode a protocol message and extract * out the SASL payload data. indata will be set * to NULL; the callback must read in the necessary @@ -228,34 +280,29 @@ enum sasl_message_type { * SASL message (again, must be free()d by the caller). * NETSEC_SASL_WRITE - Generate a protocol message to send over the * network. indata/indatasize will contain the - * SASL payload data. outdata/outdatasize should - * contain the complete protocol message. Alternatively - * the plugin can write the data to the network - * directly. + * SASL payload data. * NETSEC_SASL_FINISH - Process the final SASL message exchange; at * this point SASL exchange should have completed * and we should get a message back from the server * telling us whether or not authentication is - * successful. All buffer parameters are NULL. + * successful; the plugin should return OK/NOTOK + * to indicate whether or not the authentication + * was successful. All buffer parameters are NULL. * NETSEC_SASL_CANCEL - Generate a protocol message that cancels the - * SASL protocol exchange; outdata/outdatasize - * should contain this message. + * SASL protocol exchange; the plugin should + * send this message. All buffer parameters are NULL. * * The callback should return OK on success, NOTOK on failure. Depending * at the point of the authentication exchange, the callback may be asked * to generate a cancel message. - * - * Some higher-level notes in terms of protocol management: - * - * Any data returned in outdata should consist of allocated data that - * the sasl routines is expected to free. */ 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 @@ -268,19 +315,20 @@ typedef int (*netsec_sasl_callback)(enum sasl_message_type mtype, * Arguments: * * ns_context - Network security context - * hostname - Fully qualified hostname of remote host. * service - Service name (set to NULL to disable SASL). * 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. */ -int netsec_set_sasl_params(netsec_context *ns_context, const char *hostname, - const char *service, const char *mechanism, - netsec_sasl_callback callback, char **errstr); +int netsec_set_sasl_params(netsec_context *ns_context, const char *service, + const char *mechanism, + netsec_sasl_callback callback, + void *context, char **errstr); /* * Start SASL negotiation. The Netsec library will use the callbacks @@ -310,7 +358,25 @@ int netsec_negotiate_sasl(netsec_context *ns_context, const char *mechlist, * supported or in use. */ -char *netsec_get_sasl_mechanism(netsec_context *ns_context); +char *netsec_get_sasl_mechanism(netsec_context *ns_context) PURE; + +/* + * Returns the SASL strength security factor (SSF) for the negotiated + * authentication mechanism. + * + * The exact meaning of the SSF depends on the mechanism chosen, but in + * general: + * + * 0 - No encryption or integrity protection via SASL. + * 1 - Integrity protection only. + * >1 - Encryption + * + * The SSF is distinct from any encryption that is negotiated by TLS; + * if TLS is negotiated then the netsec SASL code will automatically disable + * any attempt to negotiate a security layer and thus the SSF will be 0. + */ + +int netsec_get_sasl_ssf(netsec_context *ns_context) PURE; /* * Set the OAuth service name used to retrieve the OAuth parameters from @@ -332,17 +398,23 @@ int netsec_set_oauth_service(netsec_context *ns_context, const char *service); * Controls whether or not TLS will be negotiated for this connection. * * Note: callers still have to call netsec_tls_negotiate() to start - * TLS negotiation at the appropriate point in the protocol. + * TLS negotiation at the appropriate point in the protocol. The + * remote hostname (controlled by netsec_set_hostname()) should have + * already been set before this function is called unless certificate + * verification is disabled. * * Arguments * * tls - If nonzero, enable TLS. Otherwise disable TLS * negotiation. + * noverify - If nonzero, disable server certificate and hostname + * validation. * * Returns NOTOK if TLS is not supported or was unable to initialize. */ -int netsec_set_tls(netsec_context *context, int tls, char **errstr); +int netsec_set_tls(netsec_context *context, int tls, int noverify, + char **errstr); /* * Start TLS negotiation on this protocol. This connection should have @@ -370,4 +442,5 @@ int netsec_negotiate_tls(netsec_context *ns_context, char **errstr); * */ -void netsec_err(char **errstr, const char *format, ...); +void netsec_err(char **errstr, const char *format, ...) + CHECK_PRINTF(2, 3);