login-settings.c revision ed4cdfe5847a6063d5a4684a6a47b17e943922b5
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "common.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "hostpid.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "var-expand.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "settings-parser.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "master-service-settings.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include "login-settings.h"
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include <stddef.h>
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#include <unistd.h>
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistatic bool login_settings_check(void *_set, pool_t pool, const char **error_r);
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#undef DEF
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#define DEF(type, name) \
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi { type, #name, offsetof(struct login_settings, name), NULL }
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistatic struct setting_define login_setting_defines[] = {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, login_trusted_networks),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR_VARS, login_greeting),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, login_log_format_elements),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, login_log_format),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_ENUM, ssl),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_ca_file),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_cert),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_key),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_key_password),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_parameters_file),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_cipher_list),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_STR, ssl_cert_username_field),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, ssl_verify_client_cert),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, ssl_require_client_cert),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, ssl_username_from_cert),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, verbose_ssl),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, disable_plaintext_auth),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, verbose_auth),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, auth_debug),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_BOOL, verbose_proctitle),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi DEF(SET_UINT, mail_max_userip_connections),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi SETTING_DEFINE_LIST_END
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi};
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistatic struct login_settings login_default_settings = {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(login_trusted_networks) "",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(login_greeting) PACKAGE_NAME" ready.",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(login_log_format) "%$: %s",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl) "yes:no:required",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_ca_file) "",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_cert) "",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_key) "",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_key_password) "",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_parameters_file) "ssl-parameters.dat",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_cipher_list) "ALL:!LOW:!SSLv2:!EXP:!aNULL",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_cert_username_field) "commonName",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_verify_client_cert) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_require_client_cert) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(ssl_username_from_cert) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(verbose_ssl) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(disable_plaintext_auth) TRUE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(verbose_auth) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(auth_debug) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(verbose_proctitle) FALSE,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(mail_max_userip_connections) 10
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi};
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistruct setting_parser_info login_setting_parser_info = {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(module_name) "login",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(defines) login_setting_defines,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(defaults) &login_default_settings,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(type_offset) (size_t)-1,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(struct_size) sizeof(struct login_settings),
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(parent_offset) (size_t)-1,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(parent) NULL,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi MEMBER(check_func) login_settings_check
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi};
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistatic const struct setting_parser_info *default_login_set_roots[] = {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi &login_setting_parser_info,
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi NULL
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi};
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomiconst struct setting_parser_info **login_set_roots = default_login_set_roots;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi/* <settings checks> */
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomistatic int ssl_settings_check(void *_set ATTR_UNUSED, const char **error_r)
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi{
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi struct login_settings *set = _set;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#ifndef HAVE_SSL
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi *error_r = t_strdup_printf("SSL support not compiled in but ssl=%s",
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi set->ssl);
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi return FALSE;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#else
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi if (*set->ssl_cert == '\0') {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi *error_r = "ssl enabled, but ssl_cert not set";
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi return FALSE;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi }
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi if (*set->ssl_key == '\0') {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi *error_r = "ssl enabled, but ssl_key not set";
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi return FALSE;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi }
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi if (set->ssl_verify_client_cert && *set->ssl_ca_file == '\0') {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi *error_r = "ssl_verify_client_cert set, but ssl_ca_file not";
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi return FALSE;
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi }
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi#ifndef CONFIG_BINARY
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi if (*set->ssl_ca_file != '\0' && access(set->ssl_ca_file, R_OK) < 0) {
6004fdf3cc8fe87a6c35ce297d39ab68feb707b0Aki Tuomi *error_r = t_strdup_printf("ssl_ca_file: access(%s) failed: %m",
set->ssl_ca_file);
return FALSE;
}
#endif
return TRUE;
#endif
}
static bool login_settings_check(void *_set, pool_t pool, const char **error_r)
{
struct login_settings *set = _set;
set->log_format_elements_split =
p_strsplit(pool, set->login_log_format_elements, " ");
if (set->ssl_require_client_cert || set->ssl_username_from_cert) {
/* if we require valid cert, make sure we also ask for it */
set->ssl_verify_client_cert = TRUE;
}
if (strcmp(set->ssl, "no") == 0) {
/* disabled */
} else if (strcmp(set->ssl, "yes") == 0) {
if (!ssl_settings_check(set, error_r))
return FALSE;
} else if (strcmp(set->ssl, "required") == 0) {
if (!ssl_settings_check(set, error_r))
return FALSE;
set->disable_plaintext_auth = TRUE;
} else {
*error_r = t_strdup_printf("Unknown ssl setting value: %s",
set->ssl);
return FALSE;
}
return TRUE;
}
/* </settings checks> */
static const struct var_expand_table *
login_set_var_expand_table(const struct master_service_settings_input *input)
{
static struct var_expand_table static_tab[] = {
{ 'l', NULL, "lip" },
{ 'r', NULL, "rip" },
{ 'p', NULL, "pid" },
{ 's', NULL, "service" },
{ '\0', NULL, "hostname" },
{ '\0', NULL, NULL }
};
struct var_expand_table *tab;
tab = t_malloc(sizeof(static_tab));
memcpy(tab, static_tab, sizeof(static_tab));
tab[0].value = net_ip2addr(&input->local_ip);
tab[1].value = net_ip2addr(&input->remote_ip);
tab[2].value = my_pid;
tab[3].value = input->service;
tab[4].value = my_hostname;
return tab;
}
struct login_settings *
login_settings_read(struct master_service *service, pool_t pool,
const struct ip_addr *local_ip,
const struct ip_addr *remote_ip,
void ***other_settings_r)
{
struct master_service_settings_input input;
const char *error;
void **sets;
unsigned int i;
memset(&input, 0, sizeof(input));
input.roots = login_set_roots;
input.module = login_process_name;
input.service = login_protocol;
if (local_ip != NULL)
input.local_ip = *local_ip;
if (remote_ip != NULL)
input.remote_ip = *remote_ip;
/* this function always clears the previous settings pool. since we're
doing per-connection lookups, we always need to duplicate the
settings using another pool. */
if (master_service_settings_read(service, &input, &error) < 0)
i_fatal("Error reading configuration: %s", error);
sets = master_service_settings_get_others(service);
for (i = 0; sets[i] != NULL; i++) {
sets[i] = settings_dup(input.roots[i], sets[i], pool);
if (!settings_check(input.roots[i], pool, sets[i], &error)) {
const char *name = input.roots[i]->module_name;
i_fatal("settings_check(%s) failed: %s",
name != NULL ? name : "unknown", error);
}
}
settings_var_expand(&login_setting_parser_info, sets[0], pool,
login_set_var_expand_table(&input));
*other_settings_r = sets + 1;
return sets[0];
}