summaryrefslogtreecommitdiffstats
path: root/src/auths/external.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/auths/external.c')
-rw-r--r--src/auths/external.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/auths/external.c b/src/auths/external.c
new file mode 100644
index 0000000..7e7fca8
--- /dev/null
+++ b/src/auths/external.c
@@ -0,0 +1,155 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2019-2020 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* This file provides an Exim authenticator driver for
+a server to verify a client SSL certificate, using the EXTERNAL
+method defined in RFC 4422 Appendix A.
+*/
+
+
+#include "../exim.h"
+#include "external.h"
+
+/* Options specific to the external authentication mechanism. */
+
+optionlist auth_external_options[] = {
+ { "client_send", opt_stringptr, OPT_OFF(auth_external_options_block, client_send) },
+ { "server_param2", opt_stringptr, OPT_OFF(auth_external_options_block, server_param2) },
+ { "server_param3", opt_stringptr, OPT_OFF(auth_external_options_block, server_param3) },
+};
+
+/* Size of the options list. An extern variable has to be used so that its
+address can appear in the tables drtables.c. */
+
+int auth_external_options_count = nelem(auth_external_options);
+
+/* Default private options block for the authentication method. */
+
+auth_external_options_block auth_external_option_defaults = {
+ .server_param2 = NULL,
+ .server_param3 = NULL,
+
+ .client_send = NULL,
+};
+
+
+#ifdef MACRO_PREDEF
+
+/* Dummy values */
+void auth_external_init(auth_instance *ablock) {}
+int auth_external_server(auth_instance *ablock, uschar *data) {return 0;}
+int auth_external_client(auth_instance *ablock, void * sx,
+ int timeout, uschar *buffer, int buffsize) {return 0;}
+
+#else /*!MACRO_PREDEF*/
+
+
+
+
+/*************************************************
+* Initialization entry point *
+*************************************************/
+
+/* Called for each instance, after its options have been read, to
+enable consistency checks to be done, or anything else that needs
+to be set up. */
+
+void
+auth_external_init(auth_instance *ablock)
+{
+auth_external_options_block * ob = (auth_external_options_block *)ablock->options_block;
+if (!ablock->public_name) ablock->public_name = ablock->name;
+if (ablock->server_condition) ablock->server = TRUE;
+if (ob->client_send) ablock->client = TRUE;
+}
+
+
+
+/*************************************************
+* Server entry point *
+*************************************************/
+
+/* For interface, see auths/README */
+
+int
+auth_external_server(auth_instance * ablock, uschar * data)
+{
+auth_external_options_block * ob = (auth_external_options_block *)ablock->options_block;
+int rc;
+
+/* If data was supplied on the AUTH command, decode it, and split it up into
+multiple items at binary zeros. The strings are put into $auth1, $auth2, etc,
+up to a maximum. To retain backwards compatibility, they are also put int $1,
+$2, etc. If the data consists of the string "=" it indicates a single, empty
+string. */
+
+if (*data)
+ if ((rc = auth_read_input(data)) != OK)
+ return rc;
+
+/* Now go through the list of prompt strings. Skip over any whose data has
+already been provided as part of the AUTH command. For the rest, send them
+out as prompts, and get a data item back. If the data item is "*", abandon the
+authentication attempt. Otherwise, split it into items as above. */
+
+if (expand_nmax == 0) /* skip if rxd data */
+ if ((rc = auth_prompt(CUS"")) != OK)
+ return rc;
+
+if (ob->server_param2)
+ {
+ uschar * s = expand_string(ob->server_param2);
+ auth_vars[expand_nmax] = s;
+ expand_nstring[++expand_nmax] = s;
+ expand_nlength[expand_nmax] = Ustrlen(s);
+ if (ob->server_param3)
+ {
+ s = expand_string(ob->server_param3);
+ auth_vars[expand_nmax] = s;
+ expand_nstring[++expand_nmax] = s;
+ expand_nlength[expand_nmax] = Ustrlen(s);
+ }
+ }
+
+return auth_check_serv_cond(ablock);
+}
+
+
+
+/*************************************************
+* Client entry point *
+*************************************************/
+
+/* For interface, see auths/README */
+
+int
+auth_external_client(
+ auth_instance *ablock, /* authenticator block */
+ void * sx, /* smtp connextion */
+ int timeout, /* command timeout */
+ uschar *buffer, /* buffer for reading response */
+ int buffsize) /* size of buffer */
+{
+auth_external_options_block *ob =
+ (auth_external_options_block *)(ablock->options_block);
+const uschar * text = ob->client_send;
+int rc;
+
+/* We output an AUTH command with one expanded argument, the client_send option */
+
+if ((rc = auth_client_item(sx, ablock, &text, AUTH_ITEM_FIRST | AUTH_ITEM_LAST,
+ timeout, buffer, buffsize)) != OK)
+ return rc == DEFER ? FAIL : rc;
+
+if (text) auth_vars[0] = string_copy(text);
+return OK;
+}
+
+
+
+#endif /*!MACRO_PREDEF*/
+/* End of external.c */