summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2019-01-05 20:40:08 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2019-02-11 00:15:24 +0000
commitb53c265b5c7825d7fb6bb672547c44d080459d71 (patch)
tree41f6e133c24de5e551590239f2898dba9d6b06bd /src
parent37942ad83fcb6b788cceb4abe2891c92651811a7 (diff)
EXTERNAL authenticator
(cherry picked from commit c4a8c663b74a35b547d8320547079ca56b3b772e)
Diffstat (limited to 'src')
-rw-r--r--src/OS/Makefile-Base5
-rwxr-xr-xsrc/scripts/MakeLinks2
-rw-r--r--src/src/EDITME1
-rw-r--r--src/src/auths/Makefile3
-rw-r--r--src/src/auths/external.c158
-rw-r--r--src/src/auths/external.h32
-rw-r--r--src/src/config.h.defaults1
-rw-r--r--src/src/drtables.c18
8 files changed, 217 insertions, 3 deletions
diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base
index fed3134cf..79bec063b 100644
--- a/src/OS/Makefile-Base
+++ b/src/OS/Makefile-Base
@@ -135,7 +135,7 @@ OBJ_MACRO = macro_predef.o \
macro-smtp.o macro-accept.o macro-dnslookup.o macro-ipliteral.o macro-iplookup.o \
macro-manualroute.o macro-queryprogram.o macro-redirect.o \
macro-auth-spa.o macro-cram_md5.o macro-cyrus_sasl.o macro-dovecot.o macro-gsasl_exim.o \
- macro-heimdal_gssapi.o macro-plaintext.o macro-spa.o macro-authtls.o \
+ macro-heimdal_gssapi.o macro-plaintext.o macro-spa.o macro-authtls.o macro-external.o \
macro-dkim.o macro-malware.o macro-signing.o
$(OBJ_MACRO): $(MACRO_HSRC)
@@ -212,6 +212,9 @@ macro-cyrus_sasl.o : auths/cyrus_sasl.c
macro-dovecot.o: auths/dovecot.c
@echo "$(CC) -DMACRO_PREDEF auths/dovecot.c"
$(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/dovecot.c
+macro-external.o: auths/external.c
+ @echo "$(CC) -DMACRO_PREDEF auths/external.c"
+ $(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/external.c
macro-gsasl_exim.o : auths/gsasl_exim.c
@echo "$(CC) -DMACRO_PREDEF auths/gsasl_exim.c"
$(FE)$(CC) -c $(CFLAGS) -DMACRO_PREDEF $(INCLUDE) -o $@ auths/gsasl_exim.c
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index 08f4ff1f8..f69bde437 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -75,7 +75,7 @@ for f in README Makefile call_pam.c call_pwcheck.c \
gsasl_exim.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
md5.c xtextencode.c xtextdecode.c cram_md5.c cram_md5.h plaintext.c plaintext.h \
pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h sha1.c spa.c \
- spa.h tls.c tls.h
+ spa.h tls.c tls.h external.c external.h
do
ln -s ../../src/auths/$f $f
done
diff --git a/src/src/EDITME b/src/src/EDITME
index cbb080545..15360db9a 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -643,6 +643,7 @@ FIXED_NEVER_USERS=root
# AUTH_CRAM_MD5=yes
# AUTH_CYRUS_SASL=yes
# AUTH_DOVECOT=yes
+# AUTH_EXTERNAL=yes
# AUTH_GSASL=yes
# AUTH_GSASL_PC=libgsasl
# AUTH_HEIMDAL_GSSAPI=yes
diff --git a/src/src/auths/Makefile b/src/src/auths/Makefile
index 62ce9d0a9..402f1417a 100644
--- a/src/src/auths/Makefile
+++ b/src/src/auths/Makefile
@@ -7,7 +7,7 @@
OBJ = auth-spa.o call_pam.o call_pwcheck.o \
call_radius.o check_serv_cond.o cram_md5.o cyrus_sasl.o dovecot.o \
- get_data.o get_no64_data.o gsasl_exim.o heimdal_gssapi.o \
+ external.o get_data.o get_no64_data.o gsasl_exim.o heimdal_gssapi.o \
md5.o plaintext.o pwcheck.o \
spa.o tls.o xtextdecode.o xtextencode.o
@@ -36,6 +36,7 @@ xtextencode.o: $(HDRS) xtextencode.c
cram_md5.o: $(HDRS) cram_md5.c cram_md5.h
cyrus_sasl.o: $(HDRS) cyrus_sasl.c cyrus_sasl.h
dovecot.o: $(HDRS) dovecot.c dovecot.h
+external.o: $(HDRS) external.c external.h
gsasl_exim.o: $(HDRS) gsasl_exim.c gsasl_exim.h
heimdal_gssapi.o: $(HDRS) heimdal_gssapi.c heimdal_gssapi.h
plaintext.o: $(HDRS) plaintext.c plaintext.h
diff --git a/src/src/auths/external.c b/src/src/auths/external.c
new file mode 100644
index 000000000..10e1366a8
--- /dev/null
+++ b/src/src/auths/external.c
@@ -0,0 +1,158 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2019 */
+/* 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,
+ (void *)(offsetof(auth_external_options_block, client_send)) },
+ { "server_param2", opt_stringptr,
+ (void *)(offsetof(auth_external_options_block, server_param2)) },
+ { "server_param3", opt_stringptr,
+ (void *)(offsetof(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 */
diff --git a/src/src/auths/external.h b/src/src/auths/external.h
new file mode 100644
index 000000000..7d43650bb
--- /dev/null
+++ b/src/src/auths/external.h
@@ -0,0 +1,32 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2019 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* Private structure for the private options. */
+
+typedef struct {
+ uschar * server_param2;
+ uschar * server_param3;
+
+ uschar * client_send;
+} auth_external_options_block;
+
+/* Data for reading the private options. */
+
+extern optionlist auth_external_options[];
+extern int auth_external_options_count;
+
+/* Block containing default values. */
+
+extern auth_external_options_block auth_external_option_defaults;
+
+/* The entry points for the mechanism */
+
+extern void auth_external_init(auth_instance *);
+extern int auth_external_server(auth_instance *, uschar *);
+extern int auth_external_client(auth_instance *, void *, int, uschar *, int);
+
+/* End of external.h */
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index 7c2e534f3..74ec3f4df 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -24,6 +24,7 @@ Do not put spaces between # and the 'define'.
#define AUTH_CRAM_MD5
#define AUTH_CYRUS_SASL
#define AUTH_DOVECOT
+#define AUTH_EXTERNAL
#define AUTH_GSASL
#define AUTH_HEIMDAL_GSSAPI
#define AUTH_PLAINTEXT
diff --git a/src/src/drtables.c b/src/src/drtables.c
index cd12dd1da..54d03edab 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -35,6 +35,10 @@ set to NULL for those that are not compiled into the binary. */
#include "auths/dovecot.h"
#endif
+#ifdef AUTH_EXTERNAL
+#include "auths/external.h"
+#endif
+
#ifdef AUTH_GSASL
#include "auths/gsasl_exim.h"
#endif
@@ -101,6 +105,20 @@ auth_info auths_available[] = {
},
#endif
+#ifdef AUTH_EXTERNAL
+ {
+ .driver_name = US"external",
+ .options = auth_external_options,
+ .options_count = &auth_external_options_count,
+ .options_block = &auth_external_option_defaults,
+ .options_len = sizeof(auth_external_options_block),
+ .init = auth_external_init,
+ .servercode = auth_external_server,
+ .clientcode = auth_external_client,
+ .version_report = NULL
+ },
+#endif
+
#ifdef AUTH_GSASL
{
.driver_name = US"gsasl",