- debhelper
- devscripts
- dh-make
+ - dovecot-core
+ - dovecot-dev
+ - dovecot-imapd
- doxygen
- fakeroot
- firebird-dev
--- /dev/null
+# -*- text -*-
+#
+#
+# $Id$
+
+#######################################################################
+#
+# = Imap Module
+#
+# This modules validates a gives user-name user-password combination.
+# If called in Authenticate, it will look for User-Name and User-Password in Access-Request.
+# If it can find both a username and password, the module will prepare an imap login request with those credentials.
+#
+# This module can optionally perform a tls handshake, enabled with require_cert
+#
+
+imap {
+ #
+ # tls { ... }:: Configure the tls related items that control
+ # how FreeRADIUS connects to a imap server.
+ #
+ tls {
+ #
+ # .Certificate validation options
+ #
+ # Specifies how the certificate(s) presented by the imap server being contacted
+ # are validated, and which certificates (if any) to send to the imap server.
+ #
+
+ #
+ # ca_file:: PEM formatted file containing the chain to validate the imap server's cert
+ #
+ # Should usually contain a concatenation of one or more intermediary CA
+ # files, shallowest (i.e. the one that signed the imap server's cert) first, and
+ # deepest (the root CA) last.
+ #
+ # Providing a complete certificate chain here is the most common way of validating
+ # the certificate presented by a imap server.
+ #
+# ca_file = "${certdir}/cacert.pem"
+
+ #
+ # ca_issuer_file:: PEM formatted file containing the CA that signed the imap server's cert
+ #
+ # Specifies the certificate that directly signed the certificate presented by the
+ # imaps server.
+ #
+ # This configuration option can be used to prevent certificates passing validation that
+ # were signed by other intermediary CAs or root CAs in the trusted certificate chain.
+ #
+# ca_issuer_file = "${certdir}/caissuer.pem"
+
+ #
+ # ca_path:: A directory containing multiple root CA certs named by their hash
+ #
+ # See the OpenSSL documentation for more details:
+ # - https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set_default_verify_paths.html
+ # - https://www.openssl.org/docs/man1.1.1/man1/c_rehash.html
+ #
+ # This configuration option should only be used when the imap server being contacted
+ # is not known ahead of time (using a URL from an external source), and/or the CA used
+ # to sign the imap server certificate is unknown.
+ #
+# ca_path = "${certdir}"
+
+ #
+ # certificate_file:: PEM formatted file containing the certificate we present to the imap server
+ #
+ # Specifies a certificate and any intermediary CAs we should send to the imap server.
+ #
+ # This file should usually contain the client certificate file first, then any
+ # intermediary signing CAs, shallowest (direct signee of the certificate_file)
+ # to deepest (signed directly by the root CA).
+ #
+# certificate_file = /path/to/radius.pem
+
+ #
+ # private_key_file:: PEM formatted file containing the private key for the specified certificate_file
+ #
+ # Must be specified if certificate_file is being used.
+ #
+# private_key_file = /path/to/radius.key
+
+ #
+ # private_key_password:: Password used to decrypt the private key file.
+ #
+ # Should only be specified in the private_key_file is encrypted.
+ #
+# private_key_password = "supersecret"
+
+ #
+ # random_file:: Source of random data used for various cryptographic functions.
+ #
+# random_file = /dev/urandom
+
+ #
+ # check_cert:: Server certificate verification requirements.
+ #
+ # May be one of:
+ #
+ # [options="header,autowidth"]
+ # |===
+ # | Option | Description
+ # | `no` | Server certificate can be signed by any CA or be self-signed.
+ # | `yes` | Server certificate must be issued by one of the trusted CAs.
+ # |===
+ #
+ # Default is `yes`
+ #
+# check_cert = no
+
+ #
+ # request_cert:: To what degree curl should use ssl
+ #
+ # May be one of:
+ #
+ # [options="header,autowidth"]
+ # |===
+ # | Option | Description
+ # | `demand` | Require ssl validation to accept login
+ # | `never` | Do not try to establish ssl connection
+ # | `allow` | Try to establish ssl connection, continue even if it cannot
+ # |===
+ #
+ # default is 'allow'
+ #
+# require_cert = allow
+
+ #
+ # check_cert_cn:: Server certificate CN verification requirements.
+ #
+ # May be one of:
+ #
+ # [options="header,autowidth"]
+ # |===
+ # | Option | Description
+ # | `no` | Server certificate CN can be any value.
+ # | `yes` | Server certificate CN matches the host in the URI.
+ # |===
+ #
+ # Default is `yes`
+ #
+# check_cert_cn = no
+
+ #
+ # extract_cert_attrs:: Extract OIDs from presented certificates as OIDs.
+ #
+ # Default is `no`
+ #
+# extract_cert_attrs = no
+ }
+
+ #
+ # imap_uri:: It will open a connection to the server specified in and send the tls
+ # request here
+ #
+ imap_uri = "imap://127.0.0.1:1430/"
+ #
+ # timeout:: Number of milliseconds FreeRADIUS will wait for a response
+ #
+ timeout = 5000
+}
for i in \
postgresql-setup.sh \
+ imap-setup.sh \
mysql-setup.sh \
ldap-setup.sh \
redis-setup.sh; do
--- /dev/null
+protocols = imap
+
+# Disable SSL for now.
+disable_plaintext_auth = no
+
+# Authentication configuration:
+auth_verbose = yes
+auth_mechanisms = plain
+
+login_trusted_networks = 127.0.0.1
+
+# Disable delays for bad login attempts
+service anvil {
+ unix_listener anvil-auth-penalty {
+ mode = 0
+ }
+ chroot =
+}
+
+# ALL CODE BELOW THIS IS ADDED BY THE SHELL SCRIPT scripts/travis/imap-setup.sh
--- /dev/null
+#!/bin/sh -e
+
+#
+# ### This is a script to setup a dovecot imap server for testing rlm_imap
+#
+
+#
+# Declare the important path variables
+#
+
+# Directories For storing dovecot setup files
+BASEDIR=$(git rev-parse --show-toplevel)
+BUILDDIR="${BASEDIR}/build/ci/dovecot"
+CERTDIR="${BASEDIR}/raddb/certs/rsa"
+ETCDIR="${BUILDDIR}/etc"
+
+# Directories for running dovecot
+RUNDIR="${BUILDDIR}/run"
+TLSRUNDIR="${BUILDDIR}/tls_run"
+MAILDIR="${ETCDIR}/dovecot_mail"
+LOGDIR="${BUILDDIR}/log"
+
+# Important files for running dovecot
+CONF="${ETCDIR}/dovecot.conf"
+TLSCONF="${ETCDIR}/tls_dovecot.conf"
+PASSPATH="${ETCDIR}/dovecot.passwd"
+
+# The path to the two log files
+LOGPATH="${LOGDIR}/dovecot.log"
+LOGINFOPATH="${LOGDIR}/dovecot-info.log"
+
+# Used for creating `imap-stop.sh`
+TRAVISDIR="${BASEDIR}/scripts/travis"
+
+#
+# Create all the necessary files
+#
+
+# Make the build directory
+mkdir -p "${BUILDDIR}"
+
+# Create folders for running, logging, and all parents
+mkdir -p "${ETCDIR}"
+mkdir -p "${LOGDIR}"
+mkdir -p "${RUNDIR}"
+mkdir -p "${TLSRUNDIR}"
+mkdir -p "${MAILDIR}"
+
+# Make sure there is a password file
+touch "${PASSPATH}"
+
+# Make sure there are log files
+touch "${LOGPATH}"
+touch "${LOGINFOPATH}"
+
+#
+# Add users to the password file
+#
+
+# Generate passwords for the users
+USER1P=$(doveadm pw -p test1 -s CRYPT)
+USER2P=$(doveadm pw -p test2 -s CRYPT)
+USER3P=$(doveadm pw -p test3 -s CRYPT)
+
+# Add user password combinations
+echo "\
+user1:${USER1P}::::::
+" >"${PASSPATH}"
+
+echo "\
+user2:${USER2P}::::::
+" >>"${PASSPATH}"
+
+echo "\
+user3:${USER3P}::::::
+" >>"${PASSPATH}"
+
+#
+# Configure instance specific dovecot information
+#
+
+# Load the template config file for both dovecot instances
+cp "${TRAVISDIR}/dovecot/fr_dovecot.conf" "${CONF}"
+cp "${TRAVISDIR}/dovecot/fr_dovecot.conf" "${TLSCONF}"
+
+# Configure the specifics for the non_tls dovecot server
+echo "
+instance_name = "fr_dovecot"
+
+ssl = no
+
+base_dir = ${RUNDIR}
+
+service imap-login {
+ process_min_avail = 16
+ user = ${USER}
+ chroot =
+ inet_listener imap {
+ port = 1430
+ }
+} \
+" >> "${CONF}"
+
+# Configure the specifics for the tls dovecot server
+echo "
+instance_name = "fr_tls_dovecot"
+
+
+base_dir = ${TLSRUNDIR}
+
+service imap-login {
+ process_min_avail = 16
+ user = ${USER}
+ chroot =
+ inet_listener imap {
+ port = 1431
+ }
+ inet_listener imaps {
+ port = 1432
+ }
+}
+# TLS specific configurations
+ssl = required
+ssl_protocols = !SSLv3
+ssl_cert = <${CERTDIR}/server.pem
+ssl_key = <${CERTDIR}/server.key
+ssl_key_password = whatever
+ssl_ca = <${CERTDIR}/ca.pem
+
+verbose_ssl = yes
+
+# ssl_client_ca_file = <${CERTDIR}/ca.pem
+# ssl_verify_client_cert = yes
+# auth_ssl_require_client_cert=yes
+" >> "${TLSCONF}"
+
+# Make sure there is a clean imap-stop.sh file
+> ${TRAVISDIR}/imap-stop.sh
+
+#
+# Add system specific dovecot information
+#
+for CONFPATH in $CONF $TLSCONF
+do
+# Add the path to the log files
+echo "
+log_path = ${LOGPATH}
+info_log_path = ${LOGINFOPATH} \
+" >> "${CONFPATH}"
+
+# Add the Password File to the config
+echo "
+passdb {
+ driver = passwd-file
+ args = ${PASSPATH}
+}" >> "${CONFPATH}"
+
+# Add the mail directory to the config
+echo "
+mail_location = maildir:${MAILDIR} \
+" >> "${CONFPATH}"
+
+# Set user for permissions
+echo "
+default_internal_user = ${USER}
+default_login_user = ${USER} \
+" >> "${CONFPATH}"
+
+#Configure the user mailbox privileges
+echo "
+userdb {
+ driver = static
+ args = uid=${USER} gid=${USER}
+} \
+" >> "${CONFPATH}"
+
+# Run the imap server
+echo "Starting a dovecot imap server at ${CONFPATH}"
+
+if ! dovecot -c ${CONFPATH}; then
+ echo "The server failed to start up. Here is fr_dovecot.log"
+ cat ${LOGPATH}
+ echo "And here is fr_dovecot-info.log"
+ cat ${LOGINFOPATH}
+fi
+
+echo "dovecot -c ${CONFPATH} stop" >> "${TRAVISDIR}/imap-stop.sh"
+
+done
+
+exit 0
{ NULL }
};
+fr_table_num_sorted_t const fr_curl_sslcode_table[] = {
+ {"allow", CURLUSESSL_TRY },
+ {"demand", CURLUSESSL_ALL },
+ {"never", CURLUSESSL_NONE },
+};
+static size_t fr_curl_sslcode_table_len = NUM_ELEMENTS(fr_curl_sslcode_table);
+
CONF_PARSER fr_curl_tls_config[] = {
{ FR_CONF_OFFSET("ca_file", FR_TYPE_FILE_INPUT, fr_curl_tls_t, ca_file) },
{ FR_CONF_OFFSET("ca_issuer_file", FR_TYPE_FILE_INPUT, fr_curl_tls_t, ca_issuer_file) },
{ FR_CONF_OFFSET("private_key_file", FR_TYPE_FILE_INPUT, fr_curl_tls_t, private_key_file) },
{ FR_CONF_OFFSET("private_key_password", FR_TYPE_STRING | FR_TYPE_SECRET, fr_curl_tls_t, private_key_password) },
{ FR_CONF_OFFSET("random_file", FR_TYPE_STRING, fr_curl_tls_t, random_file) },
+ { FR_CONF_OFFSET("require_cert", FR_TYPE_VOID, fr_curl_tls_t, require_cert),
+ .func = cf_table_parse_int32, .uctx = &(cf_table_parse_ctx_t){ .table = fr_curl_sslcode_table, .len = &fr_curl_sslcode_table_len },
+ .dflt = "allow" },
{ FR_CONF_OFFSET("check_cert", FR_TYPE_BOOL, fr_curl_tls_t, check_cert), .dflt = "yes" },
{ FR_CONF_OFFSET("check_cert_cn", FR_TYPE_BOOL, fr_curl_tls_t, check_cert_cn), .dflt = "yes" },
{ FR_CONF_OFFSET("extract_cert_attrs", FR_TYPE_BOOL, fr_curl_tls_t, extract_cert_attrs), .dflt = "no" },
if (conf->ca_issuer_file) FR_CURL_SET_OPTION(CURLOPT_ISSUERCERT, conf->ca_issuer_file);
if (conf->ca_path) FR_CURL_SET_OPTION(CURLOPT_CAPATH, conf->ca_path);
if (conf->random_file) FR_CURL_SET_OPTION(CURLOPT_RANDOM_FILE, conf->random_file);
+ FR_CURL_SET_OPTION(CURLOPT_USE_SSL, conf->require_cert);
FR_CURL_SET_OPTION(CURLOPT_SSL_VERIFYPEER, (conf->check_cert == true) ? 1L : 0L);
FR_CURL_SET_OPTION(CURLOPT_SSL_VERIFYHOST, (conf->check_cert_cn == true) ? 2L : 0L);
char const *ca_issuer_file;
char const *ca_path;
char const *random_file;
+ long *require_cert;
bool check_cert;
bool check_cert_cn;
bool extract_cert_attrs;
--- /dev/null
+# rlm_imap
+## Metadata
+<dl>
+ <dt>category</dt><dd>authentication</dd>
+</dl>
+
+## Summary
+This module authenticates users against an IMAP server
--- /dev/null
+# Check to see if we libfreeradius-curl, as that's a hard dependency
+# which in turn depends on json-c.
+TARGETNAME :=
+-include $(top_builddir)/src/lib/curl/all.mk
+TARGET :=
+
+ifneq "$(TARGETNAME)" ""
+TARGET := rlm_imap.a
+TGT_PREREQS += libfreeradius-curl.a
+endif
+
+SOURCES := rlm_imap.c
--- /dev/null
+/*
+ * This program is is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file rlm_imap.c
+ * @brief imap server authentication.
+ *
+ * @copyright 2020 The FreeRADIUS server project
+ * @copyright 2020 Network RADIUS SARL <legal@networkradius.com>
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/server/module.h>
+#include <freeradius-devel/curl/base.h>
+/*
+ * A mapping of configuration file names to internal variables.
+ */
+static fr_dict_t const *dict_radius; /*dictionary for radius protocol*/
+static fr_dict_t const *dict_freeradius; /*internal dictionary for server*/
+
+static fr_dict_attr_t const *attr_auth_type;
+
+static fr_dict_attr_t const *attr_user_password;
+static fr_dict_attr_t const *attr_user_name;
+
+extern fr_dict_autoload_t rlm_imap_dict[];
+fr_dict_autoload_t rlm_imap_dict[] = {
+ { .out = &dict_radius, .proto = "radius" },
+ { .out = &dict_freeradius, .proto = "freeradius" },
+ { NULL }
+};
+
+extern fr_dict_attr_autoload_t rlm_imap_dict_attr[];
+fr_dict_attr_autoload_t rlm_imap_dict_attr[] = {
+ { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
+ { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
+ { .out = &attr_user_password, .name = "User-Password", .type = FR_TYPE_STRING, .dict = &dict_radius },
+ { NULL },
+};
+
+typedef struct {
+ fr_dict_enum_t *auth_type;
+ char const *name;
+ char const *imap_uri; //!<URL of imap server
+ fr_time_delta_t timeout; //!<Timeout for connection and server response
+ fr_curl_tls_t tls;
+} rlm_imap_t;
+
+typedef struct {
+ rlm_imap_t const *inst; //!< Instance of rlm_imap.
+ fr_curl_handle_t *mhandle; //!< Thread specific multi handle. Serves as the dispatch and coralling structure for imap requests.
+} rlm_imap_thread_t;
+
+static const CONF_PARSER module_config[] = {
+ { FR_CONF_OFFSET("imap_uri", FR_TYPE_STRING, rlm_imap_t, imap_uri) },
+ { FR_CONF_OFFSET("timeout",FR_TYPE_TIME_DELTA, rlm_imap_t, timeout) },
+ { FR_CONF_OFFSET("tls", FR_TYPE_SUBSECTION, rlm_imap_t, tls), .subcs = (void const *) fr_curl_tls_config },//!<loading the tls values
+ CONF_PARSER_TERMINATOR
+};
+
+/*
+ * Check to see that we have a username and password
+ * print out the username
+ * if a value is missing return NOOP
+ */
+static rlm_rcode_t mod_authorize(void *instance, UNUSED void *thread, REQUEST *request)
+{
+ VALUE_PAIR *vp;
+ rlm_imap_t *inst = instance;
+
+ vp = fr_pair_find_by_da(request->packet->vps, attr_user_name, TAG_ANY);
+ if (vp == NULL) return RLM_MODULE_NOOP;
+ RDEBUG2("Authorizing: %pP", vp);
+ vp = fr_pair_find_by_da(request->packet->vps, attr_user_password, TAG_ANY);
+ if (vp == NULL) return RLM_MODULE_NOOP;
+ /*
+ *Check to see if there is already a section that will be working on the request
+ */
+ if (!module_section_type_set(request, attr_auth_type, inst->auth_type)) return RLM_MODULE_NOOP;
+
+ return RLM_MODULE_OK;
+}
+/*
+ *Called when the IMAP server responds
+ *It checks if the response was CURLE_OK
+ *If it wasn't we returns REJECT, if it was we returns OK
+*/
+static rlm_rcode_t CC_HINT(nonnull) mod_authenticate_resume(void *instance, UNUSED void *thread, REQUEST *request, void *rctx)
+{
+ fr_curl_io_request_t *randle = rctx;
+ rlm_imap_t *inst = instance;
+ fr_curl_tls_t *tls;
+ long curl_out;
+ long curl_out_valid;
+
+ tls = &inst->tls;
+
+ curl_out_valid = curl_easy_getinfo(randle->candle, CURLINFO_SSL_VERIFYRESULT, &curl_out);
+ if(curl_out_valid == CURLE_OK){
+ RDEBUG2("server certificate %s verified\n", curl_out? "was":"not");
+ } else {
+ RDEBUG2("server certificate result not found");
+ }
+
+ if (randle->result != CURLE_OK) {
+ talloc_free(randle);
+ return RLM_MODULE_REJECT;
+ }
+
+ if (tls->extract_cert_attrs) fr_curl_response_certinfo(request, randle);
+
+ talloc_free(randle);
+ return RLM_MODULE_OK;
+}
+/*
+ * Checks that there is a User-Name and User-Password field in the request
+ * Checks that User-Password is not Blank
+ * Sets the: username, password
+ * website URI
+ * timeout information
+ * and TLS information
+ * Then it queues the request and yeilds until a response is given
+ * When it responds, mod_authenticate_resume is called
+ */
+static rlm_rcode_t CC_HINT(nonnull(1,2)) mod_authenticate(void *instance, void *thread, REQUEST *request)
+{
+ VALUE_PAIR const *username;
+ VALUE_PAIR const *password;
+ rlm_imap_t *inst = instance;
+
+ rlm_imap_thread_t *t = thread;
+ fr_curl_io_request_t *randle;
+
+ fr_time_delta_t timeout = inst->timeout;
+ char const *imap_uri = inst->imap_uri;
+
+ randle = fr_curl_io_request_alloc(request);
+ if (!randle){
+ error:
+ return RLM_MODULE_FAIL;
+ }
+
+ username = fr_pair_find_by_da(request->packet->vps, attr_user_name, TAG_ANY);
+ password = fr_pair_find_by_da(request->packet->vps, attr_user_password, TAG_ANY);
+
+ if (!username) {
+ REDEBUG("Attribute \"User-Name\" is required for authentication");
+ return RLM_MODULE_INVALID;
+ }
+ if (!password) {
+ RDEBUG2("Attribute \"User-Password\" is required for authentication");
+ return RLM_MODULE_INVALID;
+ }
+ if (password->vp_length == 0) {
+ RDEBUG2("\"User-Password\" must not be empty");
+ return RLM_MODULE_INVALID;
+ }
+
+ FR_CURL_SET_OPTION(CURLOPT_USERNAME, username->vp_strvalue);
+ FR_CURL_SET_OPTION(CURLOPT_PASSWORD, password->vp_strvalue);
+
+ FR_CURL_SET_OPTION(CURLOPT_DEFAULT_PROTOCOL, "imap");
+ FR_CURL_SET_OPTION(CURLOPT_URL, imap_uri);
+
+ FR_CURL_SET_OPTION(CURLOPT_CONNECTTIMEOUT_MS, timeout);
+ FR_CURL_SET_OPTION(CURLOPT_TIMEOUT_MS, timeout);
+
+ FR_CURL_SET_OPTION(CURLOPT_VERBOSE, 1L);
+
+ if(fr_curl_easy_tls_init(randle, &inst->tls) != 0) return RLM_MODULE_INVALID;
+
+ if(fr_curl_io_request_enqueue(t->mhandle, request, randle)) return RLM_MODULE_INVALID;
+
+ return unlang_module_yield(request, mod_authenticate_resume, NULL, randle);
+}
+
+static int mod_bootstrap(void *instance, CONF_SECTION *conf)
+{
+ char const *name;
+ rlm_imap_t *inst = instance;
+ name = cf_section_name2(conf);
+ if (!name) name = cf_section_name1(conf);
+ inst->name = name;
+ if (fr_dict_enum_add_name_next(fr_dict_attr_unconst(attr_auth_type), inst->name) < 0) {
+ PERROR("Failed adding %s alias", attr_auth_type->name);
+ return -1;
+ }
+ inst->auth_type = fr_dict_enum_by_name(attr_auth_type, inst->name, -1);
+ fr_assert(inst->auth_type);
+ return 0;
+}
+/*
+ * Initialize global curl instance
+ */
+static int mod_load(void)
+{
+ if (fr_curl_init() < 0) return -1;
+ return 0;
+}
+/*
+ * Close global curl instance
+ */
+static void mod_unload(void)
+{
+ fr_curl_free();
+}
+/*
+ * Initialie a new thread with a curl instance
+ */
+static int mod_thread_instantiate(UNUSED CONF_SECTION const *conf, void *instance, fr_event_list_t *el, void *thread)
+{
+ rlm_imap_thread_t *t = thread;
+ fr_curl_handle_t *mhandle;
+
+ t->inst = instance;
+
+ mhandle = fr_curl_io_init(t, el, false);
+ if (!mhandle) return -1;
+ t->mhandle = mhandle;
+
+ return 0;
+}
+/*
+ * Close the thread and free the memory
+ */
+static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread)
+{
+ rlm_imap_thread_t *t = thread;
+ talloc_free(t->mhandle); /* Ensure this is shutdown before the pool */
+ return 0;
+}
+/*
+ * External module to call rlm_imap's functions
+ */
+extern module_t rlm_imap;
+module_t rlm_imap = {
+ .magic = RLM_MODULE_INIT,
+ .name = "imap",
+ .type = RLM_TYPE_THREAD_SAFE,
+ .inst_size = sizeof(rlm_imap_t),
+ .thread_inst_size = sizeof(rlm_imap_thread_t),
+ .config = module_config,
+ .onload = mod_load,
+ .unload = mod_unload,
+ .bootstrap = mod_bootstrap,
+ .thread_instantiate = mod_thread_instantiate,
+ .thread_detach = mod_thread_detach,
+
+ .methods = {
+ [MOD_AUTHENTICATE] = mod_authenticate,
+ [MOD_AUTHORIZE] = mod_authorize,
+ },
+};
#
# Remove things which are known to fail on travis.
+# Or which are known to have long runtimes
#
ifeq "$(TRAVIS)" "1"
-FILES_SKIP := $(filter icmp/%,$(FILES))
+ FILES_SKIP := $(filter icmp/%,$(FILES))
+else ifneq "$(RUN_SLOW_TESTS)" "1"
+ FILES_SKIP += $(filter imap/auth_bad%,$(FILES))
endif
#
--- /dev/null
+#
+# Test the "imap" module
+#
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'user2'
+User-Password = 'test_fail'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Reject
+
--- /dev/null
+imap.authenticate
+if (reject) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'fail_user'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Reject
+
--- /dev/null
+imap.authenticate
+if (reject) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'user1'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Accept
+
--- /dev/null
+imap.authenticate
+if (ok) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
--- /dev/null
+#
+# Test the "imap" module
+#
--- /dev/null
+
+# Input packet
+#
+User-Name = 'user1'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Reject
+
--- /dev/null
+imap_bad_tls.authenticate
+if (ok) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
--- /dev/null
+#IMAP unit test config
+
+imap imap_bad_tls{
+ imap_uri = "127.0.0.1:1431"
+ timeout = 1000
+
+ tls {
+ ca_file = "$ENV{top_srcdir}raddb/certs/rsa/client.pem"
+
+ certificate_file = "$ENV{top_srcdir}raddb/certs/rsa/client.pem"
+
+ private_key_file = "$ENV{top_srcdir}raddb/certs/rsa/client.key"
+
+ private_key_password = "whatever"
+
+ random_file = /dev/urandom
+
+ check_cert_cn = no
+
+ require_cert = demand
+
+ extract_cert_attrs = yes
+ }
+
+}
+
+
+
+
+
--- /dev/null
+#
+# Test the "imap" module
+#
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'user1'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Accept
+
--- /dev/null
+imap_try_tls.authenticate
+
+# if (&request:cert-attrs.Issuer) {
+# test_fail
+#}
+# else {
+# test_pass
+#}
+
+
+if (ok) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
+
+if (&request:TLS-Cert-Issuer =~ /@example\.org/) {
+ test_pass
+} else {
+ test_fail
+}
+
--- /dev/null
+#IMAP unit test config
+
+imap imap_try_tls {
+ imap_uri = "127.0.0.1:1431"
+ timeout = 1000
+
+ tls {
+ ca_file = "$ENV{top_srcdir}raddb/certs/rsa/ca.pem"
+
+ certificate_file = "$ENV{top_srcdir}raddb/certs/rsa/client.pem"
+
+ private_key_file = "$ENV{top_srcdir}raddb/certs/rsa/client.key"
+
+ private_key_password = "whatever"
+
+ random_file = /dev/urandom
+
+ check_cert_cn = no
+
+ require_cert = allow
+
+ extract_cert_attrs = yes
+ }
+
+}
--- /dev/null
+#
+# Test the "imap" module
+#
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'user1'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Accept
+
--- /dev/null
+imap_tls.authenticate
+
+# if (&request:cert-attrs.Issuer) {
+# test_fail
+#}
+# else {
+# test_pass
+#}
+
+
+if (ok) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
+
+if (&request:TLS-Cert-Issuer =~ /@example\.org/) {
+ test_pass
+} else {
+ test_fail
+}
+
--- /dev/null
+#IMAP unit test config
+
+imap imap_tls {
+ imap_uri = "127.0.0.1:1431"
+ timeout = 1000
+
+ tls {
+ ca_file = "$ENV{top_srcdir}raddb/certs/rsa/ca.pem"
+
+ certificate_file = "$ENV{top_srcdir}raddb/certs/rsa/client.pem"
+
+ private_key_file = "$ENV{top_srcdir}raddb/certs/rsa/client.key"
+
+ private_key_password = "whatever"
+
+ random_file = /dev/urandom
+
+ check_cert_cn = no
+
+ require_cert = demand
+
+ extract_cert_attrs = yes
+ }
+
+}
--- /dev/null
+#IMAP unit test config
+imap {
+ imap_uri = "127.0.0.1:1430"
+ timeout = 1000
+}
--- /dev/null
+#
+# Test the "imap_plaintext" module
+#
--- /dev/null
+#
+# Input packet
+#
+User-Name = 'user1'
+User-Password = 'test1'
+
+#
+# Expected answer
+#
+Packet-Type == Access-Accept
+
--- /dev/null
+imap_plaintext.authenticate
+if (ok) {
+ update control {
+ &Auth-Type := Accept
+ }
+}
+else {
+ reject
+}
--- /dev/null
+imap_plaintext {
+ imap_uri = "127.0.0.1:1431"
+ timeout = 1000
+}
+