]> diplodocus.org Git - nmh/blobdiff - h/netsec.h
Fix invalid pointer arithmetic.
[nmh] / h / netsec.h
index ef0d521d2c491fe4c6fc199c54b3fad7c32700cf..3e7975b417f742b78cfa3312dc06924d24893394 100644 (file)
@@ -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.
  */
 
  *
  * 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;
 
 /*
 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
 
 /*
  * 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
  *
  * 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
 
 /*
  * 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
  * 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.
 
 /*
  * 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);
 
 
 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.
  *
 /*
  * 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.
  */
 
  * 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
 
 /*
  * 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);
 
 
 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.
  *
 /*
  * 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.
  */
 
  * 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);
 
 /*
                      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,
  */
 
 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.
 
 /*
  * 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,
  */
 
 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.
 
 /*
  * 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
  * 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).
  *
  * 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.
  * 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
  * 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 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
  * 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
  * 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.
  *
  * 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,
  */
 
 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
 
 /*
  * 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
  * 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 
  * 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.
  */
 
  * 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
 
 /*
  * 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.
  */
 
  * 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
 
 /*
  * 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
  * 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.
  *
  * 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.
  */
 
  *
  * 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
 
 /*
  * 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);