-/*
- * 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;
/*
/*
* Shuts down the security context for a connection and frees all
- * associated resources.
+ * associated resources. Will unconditionally close the network socket
+ * as well.
*
* Arguments:
*
* 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 netset_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.
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.
+ *
+ * Arguments:
+ *
+ * ns_context - Network security context
+ *
+ * Returns "1" if snoop is enabled, 0 if it is not.
+ */
+
+int netsec_get_snoop(netsec_context *ns_context) PURE;
+
/*
* Sets "snoop" status; if snoop is set to a nonzero value, network traffic
* will be logged on standard error.
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.
+ *
+ * Arguments:
+ *
+ * ns_context - Network security context
+ * timeout - Read timeout, in seconds.
+ */
+
+void netsec_set_timeout(netsec_context *ns_context, int timeout);
+
/*
* Read a "line" from the network. This reads one CR/LF terminated line.
* Returns a pointer to a NUL-terminated string. This memory is valid
* until the next call to any read function. Will return an error if
- * the line does not terminated with CR/LF. Note that this will not work
- * if the data might have embedded NULs.
+ * the line does not terminate with a CR/LF.
*
* Arguments:
*
* ns_context - Network security context
+ * length - Returned length of string
* errstr - Error string
*
* Returns pointer to string, or NULL on error.
*/
-char *netsec_readline(netsec_context *ns_context, char **errstr);
+char *netsec_readline(netsec_context *ns_context, size_t *length,
+ char **errstr);
/*
* Read bytes from the network.
*/
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.
+ *
+ * Arguments:
+ *
+ * ns_context - Network security context
+ * errstr - Error string
+ * format - Format string
+ * ap - stdarg list.
+ *
+ * Returns OK on success, NOTOK on error.
+ */
+
+int netsec_vprintf(netsec_context *ns_context, char **errstr,
+ const char *format, va_list ap) CHECK_PRINTF(3, 0);
/*
* Flush any buffered bytes to the network.
NETSEC_SASL_START, /* Start of SASL authentication */
NETSEC_SASL_READ, /* Reading a message */
NETSEC_SASL_WRITE, /* Writing a message */
+ NETSEC_SASL_FINISH, /* Complete SASL exchange */
NETSEC_SASL_CANCEL /* Cancel a SASL exchange */
};
* indatasize - The size of the input data in bytes
* outdata - Output data (freed by caller)
* outdatasize - Size of output data
- * snoop - If set to true, plugin should log SASL exchange to stderr.
+ * 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.
* 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
* 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.
+ * 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; 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
unsigned int indatasize,
unsigned char **outdata,
unsigned int *outdatasize,
- int snoop, char **errstr);
+ void *context, char **errstr);
/*
* Sets the SASL parameters for this connection. If this function is
* Arguments:
*
* ns_context - Network security context
- * hostname - Fully qualified hostname of remote host.
* service - Service name (set to NULL to disable SASL).
- * mechlist - A space-separated list of mechanisms supported by the server.
* 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
* 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
* 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
*/
int netsec_negotiate_tls(netsec_context *ns_context, char **errstr);
+
+/*
+ * Allocate and format an error string; should be used by plugins
+ * to report errors.
+ *
+ * Arguments:
+ *
+ * errstr - Error string to be returned
+ * format - printf(3) format string
+ * ... - Arguments to printf(3)
+ *
+ */
+
+void netsec_err(char **errstr, const char *format, ...)
+ CHECK_PRINTF(2, 3);