mech.c revision de7f381feed323acf07f990150a55db67e0c6259
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "common.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "ioloop.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "buffer.h"
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#include "hash.h"
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen#include "mech.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "str.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "var-expand.h"
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#include "auth-client-connection.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include "auth-master-connection.h"
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen#include <stdlib.h>
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstruct mech_module_list *mech_modules;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenconst char *const *auth_realms;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenconst char *default_realm;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenconst char *anonymous_username;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenchar username_chars[256], username_translation[256];
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenint ssl_require_client_cert;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainenstatic int set_use_cyrus_sasl;
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainenstatic struct auth_client_request_reply failure_reply;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstatic buffer_t *auth_failures_buf;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstatic struct timeout *to_auth_failures;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mech_register_module(struct mech_module *module)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen struct mech_module_list *list;
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen list = i_new(struct mech_module_list, 1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen list->module = *module;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen list->next = mech_modules;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_modules = list;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mech_unregister_module(struct mech_module *module)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct mech_module_list **pos, *list;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen for (pos = &mech_modules; *pos != NULL; pos = &(*pos)->next) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (strcmp((*pos)->module.mech_name, module->mech_name) == 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen list = *pos;
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen *pos = (*pos)->next;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_free(list);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen break;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenconst string_t *auth_mechanisms_get_list(void)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen struct mech_module_list *list;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen string_t *str;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str = t_str_new(128);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen for (list = mech_modules; list != NULL; list = list->next)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str_append(str, list->module.mech_name);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return str;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenstatic struct mech_module *mech_module_find(const char *name)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen struct mech_module_list *list;
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen for (list = mech_modules; list != NULL; list = list->next) {
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen if (strcasecmp(list->module.mech_name, name) == 0)
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen return &list->module;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen }
c69a255a68103a50fa3f04a527281a169075403fTimo Sirainen return NULL;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mech_request_new(struct auth_client_connection *conn,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen struct auth_client_request_new *request,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen const unsigned char *data,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen mech_callback_t *callback)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen struct mech_module *mech;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen struct auth_request *auth_request;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen size_t ip_size = 1;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen if (request->ip_family == AF_INET)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen ip_size = 4;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen else if (request->ip_family != 0)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen ip_size = sizeof(auth_request->local_ip.ip);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen else
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen ip_size = 0;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen /* make sure data is NUL-terminated */
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen if (request->data_size <= ip_size*2 || request->initial_resp_idx == 0 ||
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen request->mech_idx >= request->data_size ||
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen request->protocol_idx >= request->data_size ||
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen request->initial_resp_idx > request->data_size ||
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen data[request->initial_resp_idx-1] != '\0') {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_error("BUG: Auth client %u sent corrupted request",
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen conn->pid);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen failure_reply.id = request->id;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen callback(&failure_reply, NULL, conn);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return;
87b426af6a2365c6840b14281a98c23e903bf28eTimo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech = mech_module_find((const char *)data + request->mech_idx);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (mech == NULL) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* unsupported mechanism */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_error("BUG: Auth client %u requested unsupported "
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen "auth mechanism %s", conn->pid,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen (const char *)data + request->mech_idx);
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen failure_reply.id = request->id;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen callback(&failure_reply, NULL, conn);
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen return;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen }
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#ifdef USE_CYRUS_SASL2
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen if (set_use_cyrus_sasl)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request = mech_cyrus_sasl_new(conn, request, callback);
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen else
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen#endif
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request = mech->auth_new();
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (auth_request == NULL)
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen return;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request->created = ioloop_time;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request->conn = conn;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request->id = request->id;
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen auth_request->protocol =
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen p_strdup(auth_request->pool,
687d1dee0e92229232aa8be416897b640df67d07Timo Sirainen (const char *)data + request->protocol_idx);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (request->ip_family != 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen auth_request->local_ip.family = request->ip_family;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen auth_request->remote_ip.family = request->ip_family;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memcpy(&auth_request->local_ip.ip, data, ip_size);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memcpy(&auth_request->remote_ip.ip, data + ip_size, ip_size);
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen }
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (ssl_require_client_cert &&
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen (request->flags & AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT) == 0) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* we fail without valid certificate */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (verbose) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_info("ssl-cert-check(%s): "
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen "Client didn't present valid SSL certificate",
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen get_log_prefix(auth_request));
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen auth_request_unref(auth_request);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen failure_reply.id = request->id;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen callback(&failure_reply, NULL, conn);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen return;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
72388282bf6718c39af34cfcf51438910f9d62daTimo Sirainen hash_insert(conn->auth_requests, POINTER_CAST(request->id),
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen auth_request);
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen if (!auth_request->auth_initial(auth_request, request, data, callback))
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen mech_request_free(auth_request, request->id);
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen}
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainenvoid mech_request_continue(struct auth_client_connection *conn,
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen struct auth_client_request_continue *request,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const unsigned char *data,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_callback_t *callback)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
0ce8f754204c7eeb33805993807393f74faf2cd3Timo Sirainen struct auth_request *auth_request;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen auth_request = hash_lookup(conn->auth_requests,
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen POINTER_CAST(request->id));
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen if (auth_request == NULL) {
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen /* timeouted */
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen failure_reply.id = request->id;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen callback(&failure_reply, NULL, conn);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen } else {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (!auth_request->auth_continue(auth_request,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen data, request->data_size,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen callback))
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_request_free(auth_request, request->id);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainenvoid mech_request_free(struct auth_request *auth_request, unsigned int id)
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (auth_request->conn != NULL) {
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen hash_remove(auth_request->conn->auth_requests,
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen POINTER_CAST(id));
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen auth_request_unref(auth_request);
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen}
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainenvoid mech_init_auth_client_reply(struct auth_client_request_reply *reply)
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memset(reply, 0, sizeof(*reply));
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen reply->username_idx = (uint32_t)-1;
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen reply->reply_idx = (uint32_t)-1;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainen
62394a19cba1a8df01cad66eaa9331a70464441eTimo Sirainenvoid *mech_auth_success(struct auth_client_request_reply *reply,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct auth_request *auth_request,
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const void *data, size_t data_size)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen buffer_t *buf;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256, (size_t)-1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen reply->username_idx = 0;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen buffer_append(buf, auth_request->user, strlen(auth_request->user)+1);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen if (data_size == 0)
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply->reply_idx = (uint32_t)-1;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen else {
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply->reply_idx = buffer_get_used_size(buf);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen buffer_append(buf, data, data_size);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply->result = AUTH_CLIENT_RESULT_SUCCESS;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply->data_size = buffer_get_used_size(buf);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen return buffer_get_modifyable_data(buf, NULL);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen}
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainenvoid mech_auth_finish(struct auth_request *auth_request,
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen const void *data, size_t data_size, int success)
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen{
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen struct auth_client_request_reply reply;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen void *reply_data;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen int free_request;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen if (!success) {
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen /* failure. don't announce it immediately to avoid
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen a) timing attacks, b) flooding */
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen buffer_append(auth_failures_buf,
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen &auth_request, sizeof(auth_request));
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen return;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen memset(&reply, 0, sizeof(reply));
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply.id = auth_request->id;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply.result = AUTH_CLIENT_RESULT_SUCCESS;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen /* get this before callback because it can destroy connection */
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen free_request = AUTH_MASTER_IS_DUMMY(auth_request->conn->master);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen reply_data = mech_auth_success(&reply, auth_request, data, data_size);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen auth_request->callback(&reply, reply_data, auth_request->conn);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen if (free_request) {
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen /* we don't have master process, the request is no longer
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen needed */
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen mech_request_free(auth_request, auth_request->id);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen}
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainenint mech_fix_username(char *username, const char **error_r)
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen{
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen unsigned char *p;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen for (p = (unsigned char *)username; *p != '\0'; p++) {
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen if (username_translation[*p & 0xff] != 0)
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen *p = username_translation[*p & 0xff];
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen if (username_chars[*p & 0xff] == 0) {
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen *error_r = "Username contains disallowed characters";
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen return FALSE;
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen return TRUE;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenvoid auth_request_ref(struct auth_request *request)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen{
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen request->refcount++;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenint auth_request_unref(struct auth_request *request)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen{
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen if (--request->refcount > 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen return TRUE;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen request->auth_free(request);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen return FALSE;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenstatic const char *escape_none(const char *str)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen{
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen return str;
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen}
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenconst struct var_expand_table *
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainenauth_request_get_var_expand_table(const struct auth_request *auth_request,
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen const char *(*escape_func)(const char *))
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen static struct var_expand_table static_tab[] = {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'u', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'n', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'd', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'p', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'h', NULL },
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen { 'l', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'r', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { 'P', NULL },
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen { '\0', NULL }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen };
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct var_expand_table *tab;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (escape_func == NULL)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen escape_func = escape_none;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab = t_malloc(sizeof(static_tab));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[0].value = escape_func(auth_request->user);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[1].value = escape_func(t_strcut(auth_request->user, '@'));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[2].value = strchr(auth_request->user, '@');
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (tab[2].value != NULL)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[2].value = escape_func(tab[2].value+1);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[3].value = auth_request->protocol;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* tab[4] = we have no home dir */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (auth_request->local_ip.family != 0)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[5].value = net_ip2addr(&auth_request->local_ip);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (auth_request->remote_ip.family != 0)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[6].value = net_ip2addr(&auth_request->remote_ip);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen tab[7].value = dec2str(auth_request->conn->pid);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return tab;
b29403032a7ee56c309e94d92fbf1728bacb88f4Timo Sirainen}
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenconst char *get_log_prefix(const struct auth_request *auth_request)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen#define MAX_LOG_USERNAME_LEN 64
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const char *p, *ip;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen string_t *str;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str = t_str_new(64);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (auth_request->user == NULL)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str_append(str, "?");
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen else {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* any control characters in username will be replaced by '?' */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen for (p = auth_request->user; *p != '\0'; p++) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if ((unsigned char)*p < 32)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen break;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
b29403032a7ee56c309e94d92fbf1728bacb88f4Timo Sirainen str_append_n(str, auth_request->user,
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen (size_t)(p - auth_request->user));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen for (; *p != '\0'; p++) {
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen if ((unsigned char)*p < 32)
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen str_append_c(str, '?');
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen else
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str_append_c(str, *p);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (str_len(str) > MAX_LOG_USERNAME_LEN) {
e619ecbbc00cba9e6e1e8322caa59776507fac02Timo Sirainen str_truncate(str, MAX_LOG_USERNAME_LEN);
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen str_append(str, "...");
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen }
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen ip = net_ip2addr(&auth_request->remote_ip);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (ip != NULL) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str_append_c(str, ',');
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen str_append(str, ip);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen return str_c(str);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
64510d2cc23a79d2142030bf5bade44baa490db3Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid auth_failure_buf_flush(void)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct auth_request **auth_request;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen struct auth_client_request_reply reply;
b29403032a7ee56c309e94d92fbf1728bacb88f4Timo Sirainen size_t i, size;
b29403032a7ee56c309e94d92fbf1728bacb88f4Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen size /= sizeof(*auth_request);
919733fcead68b0e9617cfff86ae5c74d097c6cdTimo Sirainen
345253fb28498b2e0a60f4a2a8644c65feee7e75Timo Sirainen memset(&reply, 0, sizeof(reply));
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen reply.result = AUTH_CLIENT_RESULT_FAILURE;
65988f5a8abed57e9894fec77105941e046d3490Timo Sirainen
0ae99441ae9ef80f435f3eb85fad16e136036b0bTimo Sirainen for (i = 0; i < size; i++) {
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen reply.id = auth_request[i]->id;
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen auth_request[i]->callback(&reply, NULL, auth_request[i]->conn);
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen mech_request_free(auth_request[i], auth_request[i]->id);
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen }
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen buffer_set_used_size(auth_failures_buf, 0);
e1b83f64e62cc3e8967c75fcc3f9b5dbb243d3b3Timo Sirainen}
919733fcead68b0e9617cfff86ae5c74d097c6cdTimo Sirainen
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainenstatic void auth_failure_timeout(void *context __attr_unused__)
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen{
1dba794aa92dc13e6afd7a50a8c33cb19d6aa235Timo Sirainen auth_failure_buf_flush();
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen}
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_plain;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_login;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_apop;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_cram_md5;
055f4599bba1874fa1148a8fa488517fa077619cTimo Sirainenextern struct mech_module mech_digest_md5;
055f4599bba1874fa1148a8fa488517fa077619cTimo Sirainenextern struct mech_module mech_ntlm;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_rpa;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenextern struct mech_module mech_anonymous;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainenvoid mech_init(void)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen{
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const char *const *mechanisms;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen const char *env;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_modules = NULL;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen memset(&failure_reply, 0, sizeof(failure_reply));
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen failure_reply.result = AUTH_CLIENT_RESULT_FAILURE;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen anonymous_username = getenv("ANONYMOUS_USERNAME");
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (anonymous_username != NULL && *anonymous_username == '\0')
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen anonymous_username = NULL;
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen /* register wanted mechanisms */
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen env = getenv("MECHANISMS");
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen if (env == NULL || *env == '\0')
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen i_fatal("MECHANISMS environment is unset");
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mechanisms = t_strsplit_spaces(env, " ");
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen while (*mechanisms != NULL) {
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen if (strcasecmp(*mechanisms, "PLAIN") == 0)
f335accff54f408a8bbb328f8098ad458f2ff58eTimo Sirainen mech_register_module(&mech_plain);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen else if (strcasecmp(*mechanisms, "LOGIN") == 0)
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_register_module(&mech_login);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen else if (strcasecmp(*mechanisms, "APOP") == 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen mech_register_module(&mech_apop);
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen else if (strcasecmp(*mechanisms, "CRAM-MD5") == 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen mech_register_module(&mech_cram_md5);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen else if (strcasecmp(*mechanisms, "DIGEST-MD5") == 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen mech_register_module(&mech_digest_md5);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen else if (strcasecmp(*mechanisms, "NTLM") == 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen mech_register_module(&mech_ntlm);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen else if (strcasecmp(*mechanisms, "RPA") == 0)
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen mech_register_module(&mech_rpa);
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen else if (strcasecmp(*mechanisms, "ANONYMOUS") == 0) {
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen if (anonymous_username == NULL) {
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen i_fatal("ANONYMOUS listed in mechanisms, "
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen "but anonymous_username not given");
2e03303e721a293d796c0287829396f5caea76eaTimo Sirainen }
050975ee630c761ab237fce7b8f84fe189bb02d2Timo Sirainen mech_register_module(&mech_anonymous);
} else {
i_fatal("Unknown authentication mechanism '%s'",
*mechanisms);
}
mechanisms++;
}
if (mech_modules == NULL)
i_fatal("No authentication mechanisms configured");
/* get our realm - note that we allocate from data stack so
this function should never be called inside I/O loop or anywhere
else where t_pop() is called */
env = getenv("REALMS");
if (env == NULL)
env = "";
auth_realms = t_strsplit_spaces(env, " ");
default_realm = getenv("DEFAULT_REALM");
if (default_realm != NULL && *default_realm == '\0')
default_realm = NULL;
env = getenv("USERNAME_CHARS");
if (env == NULL || *env == '\0') {
/* all chars are allowed */
memset(username_chars, 1, sizeof(username_chars));
} else {
memset(username_chars, 0, sizeof(username_chars));
for (; *env != '\0'; env++)
username_chars[((unsigned char)*env) & 0xff] = 1;
}
env = getenv("USERNAME_TRANSLATION");
memset(username_translation, 0, sizeof(username_translation));
if (env != NULL) {
for (; *env != '\0' && env[1] != '\0'; env += 2) {
username_translation[((unsigned char)*env) & 0xff] =
env[1];
}
}
set_use_cyrus_sasl = getenv("USE_CYRUS_SASL") != NULL;
#ifdef USE_CYRUS_SASL2
if (set_use_cyrus_sasl)
mech_cyrus_sasl_init_lib();
#endif
ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
auth_failures_buf =
buffer_create_dynamic(default_pool, 1024, (size_t)-1);
to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
}
void mech_deinit(void)
{
timeout_remove(to_auth_failures);
mech_unregister_module(&mech_plain);
mech_unregister_module(&mech_login);
mech_unregister_module(&mech_apop);
mech_unregister_module(&mech_cram_md5);
mech_unregister_module(&mech_digest_md5);
mech_unregister_module(&mech_ntlm);
mech_unregister_module(&mech_rpa);
mech_unregister_module(&mech_anonymous);
}