/* * Network security library routines for nmh. * * 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; /* * Create a network security context. Returns the allocated network * security context. Cannot fail. */ netsec_context *netsec_init(void); /* * Shuts down the security context for a connection and frees all * associated resources. * * 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); /* * Sets the file descriptor for this connection. This will be used by * the underlying communication. * * Arguments: * * ns_context - Network security context * readfd - Read file descriptor of remote connection. * writefd - Write file descriptor of remote connection */ void netsec_set_fd(netsec_context *ns_context, int readfd, int writefd); /* * Set the userid used to authenticate to this connection. * * Arguments: * * ns_context - Network security context * userid - Userid to be used for authentication. Cannot be NULL. */ void netsec_set_userid(netsec_context *ns_context, const char *userid); /* * 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); /* * Sets "snoop" status; if snoop is set to a nonzero value, network traffic * will be logged on standard error. * * Arguments: * * ns_context - Network security context * snoop - Integer value; set to nonzero to enable traffic logging */ 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 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, size_t *length, char **errstr); /* * Read bytes from the network. * * Arguments: * * ns_context - Network security context * buffer - Read buffer * size - Buffer size * errstr - Error size * * Returns number of bytes read, or -1 on error. */ ssize_t netsec_read(netsec_context *ns_context, void *buffer, size_t size, char **errstr); /* * Write data to the network; if encryption is being performed, we will * do it. Data may be buffered; use netsec_flush() to flush any outstanding * data to the network. * * Arguments: * * ns_context - Network security context * buffer - Output buffer to write to network * size - Size of data to write to network * errstr - Error string * * Returns OK on success, NOTOK otherwise. */ int netsec_write(netsec_context *ns_context, const void *buffer, size_t size, char **errstr); /* * Write bytes using printf formatting * * Arguments: * * ns_context - Network security context * errstr - Error string * format - Format string * ... - Arguments for format string * * Returns OK on success, NOTOK on error. */ int netsec_printf(netsec_context *ns_context, char **errstr, const char *format, ...); /* * 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); /* * Flush any buffered bytes to the network. * * Arguments: * * ns_context - Network security context * errstr - Error string * * Returns OK on success, NOTOK on error. */ int netsec_flush(netsec_context *ns_context, char **errstr); /* * Enumerated types for the type of message we are sending/receiving. */ enum sasl_message_type { 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 */ }; /* * The SASL callback; this is designed to parse a protocol-specific * message and return the SASL protocol message back. * * The meaning of the arguments to the callback depend on the mtype * arguments. See below for more detail. * * Arguments: * * mtype - The type of message we are processing (read/write/cancel). * indata - A pointer to any input data. * indatasize - The size of the input data in bytes * outdata - Output data (freed by caller) * outdatasize - Size of output data * 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. * 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 * data using the appropriate netsec function. * outdata/outdatasize should contain the decoded * 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. * 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. * NETSEC_SASL_CANCEL - Generate a protocol message that cancels the * SASL protocol exchange; outdata/outdatasize * should contain this message. * * 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. */ 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); /* * Sets the SASL parameters for this connection. If this function is * not called or is called with NULL for arguments, SASL authentication * will not be attempted for this connection. * * The caller must provide a callback to parse the protocol and return * the SASL protocol messages (see above for callback details). * * 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 * 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); /* * Start SASL negotiation. The Netsec library will use the callbacks * supplied in netsec_set_sasl_params() to format and parse the protocol * messages. * * Arguments: * * ns_context - Network security context * mechlist - Space-separated list of supported SASL mechanisms * errstr - An error string to be returned upon error. * * Returns OK on success, NOTOK on failure. */ int netsec_negotiate_sasl(netsec_context *ns_context, const char *mechlist, char **errstr); /* * Returns the chosen SASL mechanism by the SASL library or netsec. * * Arguments: * * ns_context - Network security context * * Returns a string containing the chosen mech, or NULL if SASL is not * supported or in use. */ char *netsec_get_sasl_mechanism(netsec_context *ns_context); /* * Set the OAuth service name used to retrieve the OAuth parameters from * user's profile. Just calling this function is not enough to guarantee * that XOAUTH2 authentication will be performed; the appropriate mechanism * name must be passed into netsec_set_sasl_params(). * * Arguments: * * ns_context - Network security context * service - OAuth2 service names. * * Returns NOTOK if OAuth2 is not supported. */ 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. * * Arguments * * tls - If nonzero, enable TLS. Otherwise disable TLS * negotiation. * * Returns NOTOK if TLS is not supported or was unable to initialize. */ int netsec_set_tls(netsec_context *context, int tls, char **errstr); /* * Start TLS negotiation on this protocol. This connection should have * netsec_set_tls() called on it. * * Arguments: * * ns_context - Network security context * errstr - Error string upon failure. * * Returns OK on success, NOTOK on failure. */ 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, ...);