Commit fb994e0a fb994e0a85011d050eb6e3e166018a5625118c20 by Sergey Poznyakoff

pop3d: configurable APOP file and safety criteria.

* include/mailutils/dbm.h (mu_dbm_init)
(mu_dbm_get_hint): New prototypes.
* include/mailutils/util.h (mu_stpcpy)
(mu_file_safety_compose): New prototypes.
* libmailutils/string/Makefile.am (libstring_la_SOURCES): Add stpcpy.c
* libmailutils/string/stpcpy.c: New file.
* libmu_cfg/tls.c (cb2_safety_checks): Use mu_file_safety_compose.
* libmu_dbm/create.c (mu_dbm_create): Use mu_dbm_init.
* libmu_dbm/dbm.c (_mu_dbm_init): Rename mu_dbm_init. All uses changed.
Use URL composing interface to create hints.
* maidag/maidag.c (mu_dbm_get_hint): New function.
* pop3d/pop3d.c (cb2_forward_file_checks): Use mu_file_safety_compose.
(apop_database_name, apop_database_safety)
(apop_database_safety_set): New variables.
(pop3d_cfg_param) <apop-database-file>
<apop-database-safety>: New configuration statements.
(main) [ENABLE_DBM]: Initialize dbm safety criteria.
* pop3d/apop.c (pop3d_apopuser): Use configured database name and
safety flags, if set.
* pop3d/pop3d.h [ENABLE_DBM] (APOP_PASSFILE): Add ".db" suffix.
(apop_database_name, apop_database_safety)
(apop_database_safety_set): New variables.
1 parent 02334735
......@@ -49,6 +49,9 @@ struct mu_dbm_impl
extern mu_url_t mu_dbm_hint;
void mu_dbm_init (void);
mu_url_t mu_dbm_get_hint (void);
int mu_dbm_register (struct mu_dbm_impl *impl);
int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db);
int mu_dbm_create (char *name, mu_dbm_file_t *db);
......
......@@ -36,6 +36,7 @@ extern "C" {
unsigned long mu_hex2ul (char hex);
size_t mu_hexstr2ul (unsigned long* ul, const char* hex, size_t len);
size_t mu_cpystr (char *dst, const char *src, size_t size);
char *mu_stpcpy (char *p, char *q);
int mu_string_unfold (char *text, size_t *plen);
int mu_true_answer_p (const char *p);
int mu_unre_set_regex (const char *str, int caseflag, char **errp);
......@@ -225,6 +226,7 @@ int mu_file_safety_check (const char *filename, int mode,
mu_list_t idlist);
int mu_file_safety_name_to_code (const char *name, int *pcode);
int mu_file_safety_name_to_error (const char *name, int *pcode);
int mu_file_safety_compose (int *res, const char *name, int defval);
#ifdef __cplusplus
}
......
......@@ -24,6 +24,7 @@ libstring_la_SOURCES = \
cstrlower.c\
cstrupper.c\
hexstr.c\
stpcpy.c\
strltrim.c\
strskip.c\
stripws.c\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <mailutils/util.h>
char *
mu_stpcpy (char *p, char *q)
{
if (q)
while ((*p = *q++))
p++;
return p;
}
......@@ -47,59 +47,26 @@ static struct mu_tls_module_config tls_settings = {
SSL_CA_FILE_CHECKS
};
static int
cb2_safety_checks (const char *name, void *data)
{
int negate = 0;
int val;
int *res = data;
int defval;
if (*name == '-')
{
negate = 1;
name++;
}
else if (*name == '+')
name++;
if (strcmp (name, "none") == 0)
{
*res = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
return 0;
}
else if (strcmp (name, "all") == 0)
{
*res = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
return 0;
}
else if (strcmp (name, "default") == 0)
{
if (data == &tls_settings.ssl_key)
val = SSL_KEY_FILE_CHECKS;
defval = SSL_KEY_FILE_CHECKS;
else if (data == &tls_settings.ssl_cert)
val = SSL_CERT_FILE_CHECKS;
defval = SSL_CERT_FILE_CHECKS;
else if (data == &tls_settings.ssl_cafile)
val = SSL_CA_FILE_CHECKS;
defval = SSL_CA_FILE_CHECKS;
else
{
mu_error (_("INTERNAL ERROR at %s:%d: unknown default value?"),
__FILE__, __LINE__);
val = MU_FILE_SAFETY_ALL;
}
defval = MU_FILE_SAFETY_ALL;
}
else if (mu_file_safety_name_to_code (name, &val))
{
if (mu_file_safety_compose (data, name, defval))
mu_error (_("unknown keyword: %s"), name);
return 0;
}
if (negate)
*res &= ~val;
else
*res |= val;
return 0;
}
static int
......
......@@ -35,7 +35,7 @@ mu_dbm_create (char *name, mu_dbm_file_t *db)
int rc;
mu_url_t url;
_mu_dbm_init ();
mu_dbm_init ();
rc = mu_url_create_hint (&url, name, 0, mu_dbm_hint);
if (rc)
return rc;
......
......@@ -54,7 +54,7 @@ _implist_cmp (const void *a, const void *b)
}
void
_mu_dbm_init ()
mu_dbm_init ()
{
int rc;
......@@ -86,33 +86,23 @@ _mu_dbm_init ()
if (!mu_dbm_hint)
{
struct mu_dbm_impl *impl;
char *urlbuf;
rc = mu_list_get (implist, 0, (void**) &impl);
if (rc)
if ((rc = mu_list_get (implist, 0, (void**) &impl)) ||
(rc = mu_url_create_null (&mu_dbm_hint)) ||
(rc = mu_url_set_scheme (mu_dbm_hint, impl->_dbm_name)))
{
mu_error (_("cannot initialize DBM hint: %s"),
mu_strerror (rc));
abort ();
}
urlbuf = malloc (strlen (impl->_dbm_name) + 4);
if (urlbuf)
{
strcpy (urlbuf, impl->_dbm_name);
strcat (urlbuf, "://");
rc = mu_url_create (&mu_dbm_hint, urlbuf);
free (urlbuf);
}
else
rc = ENOMEM;
}
if (rc)
{
mu_error (_("cannot initialize DBM hint: %s"),
mu_strerror (rc));
abort ();
}
}
mu_url_t
mu_dbm_get_hint ()
{
mu_dbm_init ();
return mu_dbm_hint;
}
int
......@@ -121,7 +111,7 @@ mu_dbm_register (struct mu_dbm_impl *impl)
int rc;
struct mu_dbm_impl *ptr;
_mu_dbm_init ();
mu_dbm_init ();
ptr = calloc (1, sizeof (*ptr));
if (!ptr)
return ENOMEM;
......@@ -151,7 +141,7 @@ mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
int safety_flags = 0;
uid_t owner_uid = getuid ();
_mu_dbm_init ();
mu_dbm_init ();
mu_url_get_flags (url, &flags);
if ((flags & (MU_URL_HOST | MU_URL_PATH)) == (MU_URL_HOST | MU_URL_PATH))
......@@ -260,6 +250,6 @@ mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
int
mu_dbm_impl_iterator (mu_iterator_t *itr)
{
_mu_dbm_init ();
mu_dbm_init ();
return mu_list_get_iterator (implist, itr);
}
......
......@@ -336,47 +336,16 @@ cb_group (void *data, mu_config_value_t *arg)
static int
cb2_forward_file_checks (const char *name, void *data)
{
int val;
int negate = 0;
if (*name == '-')
{
negate = 1;
name++;
}
else if (*name == '+')
name++;
if (strcmp (name, "none") == 0)
{
forward_file_checks = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
return 0;
}
else if (strcmp (name, "all") == 0)
{
forward_file_checks = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
return 0;
}
else if (strcmp (name, "default") == 0)
forward_file_checks = FORWARD_FILE_PERM_CHECK;
else if (mu_file_safety_name_to_code (name, &val))
{
if (mu_file_safety_compose (data, name, FORWARD_FILE_PERM_CHECK))
mu_error (_("unknown keyword: %s"), name);
return 0;
}
if (negate)
forward_file_checks &= ~val;
else
forward_file_checks |= val;
return 0;
}
static int
cb_forward_file_checks (void *data, mu_config_value_t *arg)
{
return mu_cfg_string_value_cb (arg, cb2_forward_file_checks, data);
return mu_cfg_string_value_cb (arg, cb2_forward_file_checks,
&forward_file_checks);
}
static int
......
......@@ -42,27 +42,30 @@ char *
pop3d_apopuser (const char *user)
{
char *password = NULL;
int rc;
#ifdef ENABLE_DBM
{
size_t len;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
int rc;
rc = mu_dbm_create (APOP_PASSFILE, &db);
rc = mu_dbm_create (apop_database_name, &db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to create APOP db"));
return NULL;
}
if (apop_database_safety_set)
mu_dbm_safety_set_flags (db, apop_database_safety);
rc = mu_dbm_safety_check (db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("APOP file %s fails safety check: %s"),
APOP_PASSFILE, mu_strerror (rc));
apop_database_name, mu_strerror (rc));
mu_dbm_destroy (&db);
return NULL;
}
......@@ -115,20 +118,21 @@ pop3d_apopuser (const char *user)
size_t ulen;
FILE *apop_file;
/* FIXME */
/* if (mu_check_perm (APOP_PASSFILE, 0600)) */
/* { */
/* mu_diag_output (MU_DIAG_INFO, */
/* _("bad permissions on APOP password file")); */
/* return NULL; */
/* } */
apop_file = fopen (APOP_PASSFILE, "r");
rc = mu_file_safety_check (apop_database_name, apop_database_safety,
apop_database_uid, NULL);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("APOP file %s fails safety check: %s"),
apop_database_name, mu_strerror (rc));
return NULL;
}
apop_file = fopen (apop_database_name, "r");
if (apop_file == NULL)
{
mu_diag_output (MU_DIAG_INFO,
_("unable to open APOP password file %s: %s"),
APOP_PASSFILE, mu_strerror (errno));
apop_database_name, mu_strerror (errno));
return NULL;
}
......
......@@ -31,6 +31,9 @@ int pop3d_transcript;
int debug_mode;
int tls_required;
int pop3d_xlines;
char *apop_database_name = APOP_PASSFILE;
int apop_database_safety;
int apop_database_safety_set;
#ifdef WITH_TLS
int tls_available;
......@@ -77,6 +80,22 @@ cb_bulletin_source (void *data, mu_config_value_t *val)
return 0;
}
static int
cb2_file_safety_checks (const char *name, void *data)
{
if (mu_file_safety_compose (data, name, MU_FILE_SAFETY_ALL))
mu_error (_("unknown keyword: %s"), name);
return 0;
}
static int
cb_apop_safety_checks (void *data, mu_config_value_t *arg)
{
apop_database_safety_set = 1;
return mu_cfg_string_value_cb (arg, cb2_file_safety_checks,
&apop_database_safety);
}
#ifdef ENABLE_DBM
static int
cb_bulletin_db (void *data, mu_config_value_t *val)
......@@ -98,6 +117,24 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
N_("Delete expired messages upon closing the mailbox.") },
{ "scan-lines", mu_cfg_bool, &pop3d_xlines, 0, NULL,
N_("Output the number of lines in the message in its scan listing.") },
{ "apop-database-file", mu_cfg_string, &apop_database_name, 0, NULL,
N_("set APOP database file name or URL") },
{ "apop-database-safety", mu_cfg_callback, NULL, 0, cb_apop_safety_checks,
N_("Configure safety checks for APOP database files. Argument is a list or "
"sequence of check names optionally prefixed with '+' to enable or "
"'-' to disable the corresponding check. Valid check names are:\n"
"\n"
" none disable all checks\n"
" all enable all checks\n"
" gwrfil forbid group writable files\n"
" awrfil forbid world writable files\n"
" grdfil forbid group readable files\n"
" ardfil forbid world writable files\n"
" linkwrdir forbid symbolic links in group or world writable directories\n"
" gwrdir forbid files in group writable directories\n"
" awrdir forbid files in world writable directories\n"),
N_("arg: list") },
#ifdef WITH_TLS
{ "tls-required", mu_cfg_bool, &tls_required, 0, NULL,
N_("Always require STLS before entering authentication phase.") },
......@@ -303,6 +340,16 @@ pop3d_alloc_die ()
pop3d_abquit (ERR_NO_MEM);
}
#ifdef ENABLE_DBM
static void
set_dbm_safety ()
{
mu_url_t hints = mu_dbm_get_hint ();
const char *param[] = { "+all" };
mu_url_add_param (hints, 1, param);
}
#endif
int
main (int argc, char **argv)
{
......@@ -342,6 +389,10 @@ main (int argc, char **argv)
mu_log_syslog = 1;
manlock_mandatory_locking = 1;
#ifdef ENABLE_DBM
set_dbm_safety ();
#endif
if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param,
argc, argv, 0, NULL, server))
exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */
......
......@@ -36,7 +36,7 @@
#define APOP_PASSFILE_NAME "apop"
#ifdef ENABLE_DBM
# define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME
# define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME ".db"
# define ENABLE_LOGIN_DELAY
#else
# define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME ".passwd"
......@@ -197,6 +197,9 @@ extern unsigned int idle_timeout;
extern int pop3d_transcript;
extern size_t pop3d_output_bufsize;
extern int pop3d_xlines;
extern char *apop_database_name;
extern int apop_database_safety;
extern int apop_database_safety_set;
extern pop3d_command_handler_t pop3d_find_command (const char *name);
......