summaryrefslogtreecommitdiffstats
path: root/src/xsasl/xsasl_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xsasl/xsasl_client.c')
-rw-r--r--src/xsasl/xsasl_client.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/xsasl/xsasl_client.c b/src/xsasl/xsasl_client.c
new file mode 100644
index 0000000..0bddd41
--- /dev/null
+++ b/src/xsasl/xsasl_client.c
@@ -0,0 +1,240 @@
+/*++
+/* NAME
+/* xsasl_client 3
+/* SUMMARY
+/* Postfix SASL client plug-in interface
+/* SYNOPSIS
+/* #include <xsasl.h>
+/*
+/* XSASL_CLIENT_IMPL *xsasl_client_init(client_type, path_info)
+/* const char *client_type;
+/* const char *path_info;
+/*
+/* void xsasl_client_done(implementation)
+/* XSASL_CLIENT_IMPL *implementation;
+/*
+/* ARGV *xsasl_client_types()
+/*
+/* .in +4
+/* typedef struct XSASL_CLIENT_CREATE_ARGS {
+/* VSTREAM *stream;
+/* const char *service;
+/* const char *server_name;
+/* const char *security_options;
+/* } XSASL_CLIENT_CREATE_ARGS;
+/* .in -4
+/*
+/* XSASL_CLIENT *xsasl_client_create(implementation, create_args)
+/* XSASL_CLIENT_IMPL *implementation;
+/* XSASL_CLIENT_CREATE_ARGS *create_args;
+/*
+/* XSASL_CLIENT *XSASL_CLIENT_CREATE(implementation, create_args,
+/* stream = stream_val,
+/* ...,
+/* security_options = prop_val)
+/* XSASL_CLIENT_IMPL *implementation;
+/* XSASL_CLIENT_CREATE_ARGS *create_args;
+/*
+/* void xsasl_client_free(client)
+/* XSASL_CLIENT *client;
+/*
+/* int xsasl_client_first(client, stream, mech_list, username,
+/* password, auth_method, init_resp)
+/* XSASL_CLIENT *client;
+/* const char *mech_list;
+/* const char *username;
+/* const char *password;
+/* const char **auth_method;
+/* VSTRING *init_resp;
+/*
+/* int xsasl_client_next(client, server_reply, client_reply)
+/* XSASL_CLIENT *client;
+/* const char *server_reply;
+/* VSTRING *client_reply;
+/* DESCRIPTION
+/* The XSASL_CLIENT abstraction implements a generic interface
+/* to one or more SASL authentication implementations.
+/*
+/* xsasl_client_init() is called once during process initialization.
+/* It selects a SASL implementation by name, specifies the
+/* location of a configuration file or rendez-vous point, and
+/* returns an implementation handle that can be used to generate
+/* SASL client instances. This function is typically used to
+/* initialize the underlying implementation.
+/*
+/* xsasl_client_done() disposes of an implementation handle,
+/* and allows the underlying implementation to release resources.
+/*
+/* xsasl_client_types() lists the available implementation types.
+/* The result should be destroyed by the caller.
+/*
+/* xsasl_client_create() is called at the start of an SMTP
+/* session. It generates a Postfix SASL plug-in client instance
+/* for the specified service and server name, with the specified
+/* security properties. The stream handle is stored so that
+/* encryption can be turned on after successful negotiations.
+/*
+/* XSASL_CLIENT_CREATE() is a macro that provides an interface
+/* with named parameters. Named parameters do not have to
+/* appear in a fixed order. The parameter names correspond to
+/* the member names of the XSASL_CLIENT_CREATE_ARGS structure.
+/*
+/* xsasl_client_free() is called at the end of an SMTP session.
+/* It destroys a SASL client instance, and disables further
+/* read/write operations if encryption was turned on.
+/*
+/* xsasl_client_first() produces the client input for the AUTH
+/* command. The input is an authentication method list from
+/* an EHLO response, a username and a password. On return, the
+/* method argument specifies the authentication method; storage
+/* space is owned by the underlying implementation. The initial
+/* response and client non-error replies are BASE64 encoded.
+/* Client error replies are 7-bit ASCII text without control
+/* characters, and without BASE64 encoding. They are meant for
+/* the local application, not for transmission to the server.
+/* The client may negotiate encryption of the client-server
+/* connection.
+/*
+/* The result is one of the following:
+/* .IP XSASL_AUTH_OK
+/* Success.
+/* .IP XSASL_AUTH_FORM
+/* The server reply is incorrectly formatted. The client error
+/* reply explains why.
+/* .IP XSASL_AUTH_FAIL
+/* Other error. The client error reply explains why.
+/* .PP
+/* xsasl_client_next() supports the subsequent stages of the
+/* AUTH protocol. Both the client reply and client non-error
+/* responses are BASE64 encoded. See xsasl_client_first() for
+/* other details.
+/*
+/* Arguments:
+/* .IP client
+/* SASL plug-in client handle.
+/* .IP client_reply
+/* BASE64 encoded non-error client reply, or ASCII error
+/* description for the user.
+/* .IP client_type
+/* The name of a Postfix SASL client plug_in implementation.
+/* .IP client_types
+/* Null-terminated array of strings with SASL client plug-in
+/* implementation names.
+/* .IP init_resp
+/* The AUTH command initial response.
+/* .IP implementation
+/* Implementation handle that was obtained with xsasl_client_init().
+/* .IP mech_list
+/* List of SASL mechanisms as announced by the server.
+/* .IP auth_method
+/* The AUTH command authentication method.
+/* .IP password
+/* Information from the Postfix SASL password file or equivalent.
+/* .IP path_info
+/* The value of the smtp_sasl_path parameter or equivalent.
+/* This specifies the implementation-dependent location of a
+/* configuration file, rendez-vous point, etc., and is passed
+/* unchanged to the plug-in.
+/* .IP security_options
+/* The value of the smtp_sasl_security_options parameter or
+/* equivalent. This is passed unchanged to the plug-in.
+/* .IP server_name
+/* The remote server fully qualified hostname.
+/* .IP server_reply
+/* BASE64 encoded server reply without SMTP reply code or
+/* enhanced status code.
+/* .IP service
+/* The service that is implemented by the local client (typically,
+/* "lmtp" or "smtp").
+/* .IP stream
+/* The connection between client and server.
+/* When SASL encryption is negotiated, the plug-in will
+/* transparently intercept the socket read/write operations.
+/* .IP username
+/* Information from the Postfix SASL password file.
+/* SECURITY
+/* .ad
+/* .fi
+/* The caller does not sanitize the server reply. It is the
+/* responsibility of the underlying SASL client implementation
+/* to produce 7-bit ASCII without control characters as client
+/* non-error and error replies.
+/* DIAGNOSTICS
+/* In case of error, xsasl_client_init() and xsasl_client_create()
+/* log a warning and return a null pointer.
+/*
+/* Functions that normally return XSASL_AUTH_OK will log a warning
+/* and return an appropriate result value.
+/*
+/* Panic: interface violation.
+/*
+/* Fatal errors: out of memory.
+/* SEE ALSO
+/* cyrus_security(3) Cyrus SASL security features
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this
+/* software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+
+/* SASL implementations. */
+
+#include <xsasl.h>
+#include <xsasl_cyrus.h>
+
+ /*
+ * Lookup table for available SASL client implementations.
+ */
+typedef struct {
+ char *client_type;
+ struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *);
+} XSASL_CLIENT_IMPL_INFO;
+
+static const XSASL_CLIENT_IMPL_INFO client_impl_info[] = {
+#ifdef XSASL_TYPE_CYRUS
+ XSASL_TYPE_CYRUS, xsasl_cyrus_client_init,
+#endif
+ 0,
+};
+
+/* xsasl_client_init - look up client implementation by name */
+
+XSASL_CLIENT_IMPL *xsasl_client_init(const char *client_type,
+ const char *path_info)
+{
+ const XSASL_CLIENT_IMPL_INFO *xp;
+
+ for (xp = client_impl_info; xp->client_type; xp++)
+ if (strcmp(client_type, xp->client_type) == 0)
+ return (xp->client_init(client_type, path_info));
+ msg_warn("unsupported SASL client implementation: %s", client_type);
+ return (0);
+}
+
+/* xsasl_client_types - report available implementation types */
+
+ARGV *xsasl_client_types(void)
+{
+ const XSASL_CLIENT_IMPL_INFO *xp;
+ ARGV *argv = argv_alloc(1);
+
+ for (xp = client_impl_info; xp->client_type; xp++)
+ argv_add(argv, xp->client_type, ARGV_END);
+ return (argv);
+}