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 ...@@ -49,6 +49,9 @@ struct mu_dbm_impl
49 49
50 extern mu_url_t mu_dbm_hint; 50 extern mu_url_t mu_dbm_hint;
51 51
52 void mu_dbm_init (void);
53 mu_url_t mu_dbm_get_hint (void);
54
52 int mu_dbm_register (struct mu_dbm_impl *impl); 55 int mu_dbm_register (struct mu_dbm_impl *impl);
53 int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db); 56 int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db);
54 int mu_dbm_create (char *name, mu_dbm_file_t *db); 57 int mu_dbm_create (char *name, mu_dbm_file_t *db);
......
...@@ -36,6 +36,7 @@ extern "C" { ...@@ -36,6 +36,7 @@ extern "C" {
36 unsigned long mu_hex2ul (char hex); 36 unsigned long mu_hex2ul (char hex);
37 size_t mu_hexstr2ul (unsigned long* ul, const char* hex, size_t len); 37 size_t mu_hexstr2ul (unsigned long* ul, const char* hex, size_t len);
38 size_t mu_cpystr (char *dst, const char *src, size_t size); 38 size_t mu_cpystr (char *dst, const char *src, size_t size);
39 char *mu_stpcpy (char *p, char *q);
39 int mu_string_unfold (char *text, size_t *plen); 40 int mu_string_unfold (char *text, size_t *plen);
40 int mu_true_answer_p (const char *p); 41 int mu_true_answer_p (const char *p);
41 int mu_unre_set_regex (const char *str, int caseflag, char **errp); 42 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, ...@@ -225,6 +226,7 @@ int mu_file_safety_check (const char *filename, int mode,
225 mu_list_t idlist); 226 mu_list_t idlist);
226 int mu_file_safety_name_to_code (const char *name, int *pcode); 227 int mu_file_safety_name_to_code (const char *name, int *pcode);
227 int mu_file_safety_name_to_error (const char *name, int *pcode); 228 int mu_file_safety_name_to_error (const char *name, int *pcode);
229 int mu_file_safety_compose (int *res, const char *name, int defval);
228 230
229 #ifdef __cplusplus 231 #ifdef __cplusplus
230 } 232 }
......
...@@ -24,6 +24,7 @@ libstring_la_SOURCES = \ ...@@ -24,6 +24,7 @@ libstring_la_SOURCES = \
24 cstrlower.c\ 24 cstrlower.c\
25 cstrupper.c\ 25 cstrupper.c\
26 hexstr.c\ 26 hexstr.c\
27 stpcpy.c\
27 strltrim.c\ 28 strltrim.c\
28 strskip.c\ 29 strskip.c\
29 stripws.c\ 30 stripws.c\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23 #include <mailutils/util.h>
24
25 char *
26 mu_stpcpy (char *p, char *q)
27 {
28 if (q)
29 while ((*p = *q++))
30 p++;
31 return p;
32 }
...@@ -47,58 +47,25 @@ static struct mu_tls_module_config tls_settings = { ...@@ -47,58 +47,25 @@ static struct mu_tls_module_config tls_settings = {
47 SSL_CA_FILE_CHECKS 47 SSL_CA_FILE_CHECKS
48 }; 48 };
49 49
50
51 static int 50 static int
52 cb2_safety_checks (const char *name, void *data) 51 cb2_safety_checks (const char *name, void *data)
53 { 52 {
54 int negate = 0; 53 int defval;
55 int val;
56 int *res = data;
57 54
58 if (*name == '-') 55 if (data == &tls_settings.ssl_key)
59 { 56 defval = SSL_KEY_FILE_CHECKS;
60 negate = 1; 57 else if (data == &tls_settings.ssl_cert)
61 name++; 58 defval = SSL_CERT_FILE_CHECKS;
62 } 59 else if (data == &tls_settings.ssl_cafile)
63 else if (*name == '+') 60 defval = SSL_CA_FILE_CHECKS;
64 name++; 61 else
65
66 if (strcmp (name, "none") == 0)
67 {
68 *res = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
69 return 0;
70 }
71 else if (strcmp (name, "all") == 0)
72 {
73 *res = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
74 return 0;
75 }
76 else if (strcmp (name, "default") == 0)
77 {
78 if (data == &tls_settings.ssl_key)
79 val = SSL_KEY_FILE_CHECKS;
80 else if (data == &tls_settings.ssl_cert)
81 val = SSL_CERT_FILE_CHECKS;
82 else if (data == &tls_settings.ssl_cafile)
83 val = SSL_CA_FILE_CHECKS;
84 else
85 {
86 mu_error (_("INTERNAL ERROR at %s:%d: unknown default value?"),
87 __FILE__, __LINE__);
88 val = MU_FILE_SAFETY_ALL;
89 }
90 }
91 else if (mu_file_safety_name_to_code (name, &val))
92 { 62 {
93 mu_error (_("unknown keyword: %s"), name); 63 mu_error (_("INTERNAL ERROR at %s:%d: unknown default value?"),
94 return 0; 64 __FILE__, __LINE__);
65 defval = MU_FILE_SAFETY_ALL;
95 } 66 }
96 67 if (mu_file_safety_compose (data, name, defval))
97 if (negate) 68 mu_error (_("unknown keyword: %s"), name);
98 *res &= ~val;
99 else
100 *res |= val;
101
102 return 0; 69 return 0;
103 } 70 }
104 71
......
...@@ -35,7 +35,7 @@ mu_dbm_create (char *name, mu_dbm_file_t *db) ...@@ -35,7 +35,7 @@ mu_dbm_create (char *name, mu_dbm_file_t *db)
35 int rc; 35 int rc;
36 mu_url_t url; 36 mu_url_t url;
37 37
38 _mu_dbm_init (); 38 mu_dbm_init ();
39 rc = mu_url_create_hint (&url, name, 0, mu_dbm_hint); 39 rc = mu_url_create_hint (&url, name, 0, mu_dbm_hint);
40 if (rc) 40 if (rc)
41 return rc; 41 return rc;
......
...@@ -54,7 +54,7 @@ _implist_cmp (const void *a, const void *b) ...@@ -54,7 +54,7 @@ _implist_cmp (const void *a, const void *b)
54 } 54 }
55 55
56 void 56 void
57 _mu_dbm_init () 57 mu_dbm_init ()
58 { 58 {
59 int rc; 59 int rc;
60 60
...@@ -86,42 +86,32 @@ _mu_dbm_init () ...@@ -86,42 +86,32 @@ _mu_dbm_init ()
86 if (!mu_dbm_hint) 86 if (!mu_dbm_hint)
87 { 87 {
88 struct mu_dbm_impl *impl; 88 struct mu_dbm_impl *impl;
89 char *urlbuf; 89
90 90 if ((rc = mu_list_get (implist, 0, (void**) &impl)) ||
91 rc = mu_list_get (implist, 0, (void**) &impl); 91 (rc = mu_url_create_null (&mu_dbm_hint)) ||
92 if (rc) 92 (rc = mu_url_set_scheme (mu_dbm_hint, impl->_dbm_name)))
93 { 93 {
94 mu_error (_("cannot initialize DBM hint: %s"), 94 mu_error (_("cannot initialize DBM hint: %s"),
95 mu_strerror (rc)); 95 mu_strerror (rc));
96 abort (); 96 abort ();
97 } 97 }
98 urlbuf = malloc (strlen (impl->_dbm_name) + 4);
99 if (urlbuf)
100 {
101 strcpy (urlbuf, impl->_dbm_name);
102 strcat (urlbuf, "://");
103 rc = mu_url_create (&mu_dbm_hint, urlbuf);
104 free (urlbuf);
105 }
106 else
107 rc = ENOMEM;
108
109 if (rc)
110 {
111 mu_error (_("cannot initialize DBM hint: %s"),
112 mu_strerror (rc));
113 abort ();
114 }
115 } 98 }
116 } 99 }
117 100
101 mu_url_t
102 mu_dbm_get_hint ()
103 {
104 mu_dbm_init ();
105 return mu_dbm_hint;
106 }
107
118 int 108 int
119 mu_dbm_register (struct mu_dbm_impl *impl) 109 mu_dbm_register (struct mu_dbm_impl *impl)
120 { 110 {
121 int rc; 111 int rc;
122 struct mu_dbm_impl *ptr; 112 struct mu_dbm_impl *ptr;
123 113
124 _mu_dbm_init (); 114 mu_dbm_init ();
125 ptr = calloc (1, sizeof (*ptr)); 115 ptr = calloc (1, sizeof (*ptr));
126 if (!ptr) 116 if (!ptr)
127 return ENOMEM; 117 return ENOMEM;
...@@ -151,7 +141,7 @@ mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db) ...@@ -151,7 +141,7 @@ mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
151 int safety_flags = 0; 141 int safety_flags = 0;
152 uid_t owner_uid = getuid (); 142 uid_t owner_uid = getuid ();
153 143
154 _mu_dbm_init (); 144 mu_dbm_init ();
155 145
156 mu_url_get_flags (url, &flags); 146 mu_url_get_flags (url, &flags);
157 if ((flags & (MU_URL_HOST | MU_URL_PATH)) == (MU_URL_HOST | MU_URL_PATH)) 147 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) ...@@ -260,6 +250,6 @@ mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
260 int 250 int
261 mu_dbm_impl_iterator (mu_iterator_t *itr) 251 mu_dbm_impl_iterator (mu_iterator_t *itr)
262 { 252 {
263 _mu_dbm_init (); 253 mu_dbm_init ();
264 return mu_list_get_iterator (implist, itr); 254 return mu_list_get_iterator (implist, itr);
265 } 255 }
......
...@@ -336,47 +336,16 @@ cb_group (void *data, mu_config_value_t *arg) ...@@ -336,47 +336,16 @@ cb_group (void *data, mu_config_value_t *arg)
336 static int 336 static int
337 cb2_forward_file_checks (const char *name, void *data) 337 cb2_forward_file_checks (const char *name, void *data)
338 { 338 {
339 int val; 339 if (mu_file_safety_compose (data, name, FORWARD_FILE_PERM_CHECK))
340 int negate = 0; 340 mu_error (_("unknown keyword: %s"), name);
341
342 if (*name == '-')
343 {
344 negate = 1;
345 name++;
346 }
347 else if (*name == '+')
348 name++;
349
350 if (strcmp (name, "none") == 0)
351 {
352 forward_file_checks = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
353 return 0;
354 }
355 else if (strcmp (name, "all") == 0)
356 {
357 forward_file_checks = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
358 return 0;
359 }
360 else if (strcmp (name, "default") == 0)
361 forward_file_checks = FORWARD_FILE_PERM_CHECK;
362 else if (mu_file_safety_name_to_code (name, &val))
363 {
364 mu_error (_("unknown keyword: %s"), name);
365 return 0;
366 }
367
368 if (negate)
369 forward_file_checks &= ~val;
370 else
371 forward_file_checks |= val;
372
373 return 0; 341 return 0;
374 } 342 }
375 343
376 static int 344 static int
377 cb_forward_file_checks (void *data, mu_config_value_t *arg) 345 cb_forward_file_checks (void *data, mu_config_value_t *arg)
378 { 346 {
379 return mu_cfg_string_value_cb (arg, cb2_forward_file_checks, data); 347 return mu_cfg_string_value_cb (arg, cb2_forward_file_checks,
348 &forward_file_checks);
380 } 349 }
381 350
382 static int 351 static int
......
...@@ -42,27 +42,30 @@ char * ...@@ -42,27 +42,30 @@ char *
42 pop3d_apopuser (const char *user) 42 pop3d_apopuser (const char *user)
43 { 43 {
44 char *password = NULL; 44 char *password = NULL;
45 int rc;
45 46
46 #ifdef ENABLE_DBM 47 #ifdef ENABLE_DBM
47 { 48 {
48 size_t len; 49 size_t len;
49 mu_dbm_file_t db; 50 mu_dbm_file_t db;
50 struct mu_dbm_datum key, data; 51 struct mu_dbm_datum key, data;
51 int rc;
52 52
53 rc = mu_dbm_create (APOP_PASSFILE, &db); 53 rc = mu_dbm_create (apop_database_name, &db);
54 if (rc) 54 if (rc)
55 { 55 {
56 mu_diag_output (MU_DIAG_ERROR, _("unable to create APOP db")); 56 mu_diag_output (MU_DIAG_ERROR, _("unable to create APOP db"));
57 return NULL; 57 return NULL;
58 } 58 }
59 59
60 if (apop_database_safety_set)
61 mu_dbm_safety_set_flags (db, apop_database_safety);
62
60 rc = mu_dbm_safety_check (db); 63 rc = mu_dbm_safety_check (db);
61 if (rc) 64 if (rc)
62 { 65 {
63 mu_diag_output (MU_DIAG_ERROR, 66 mu_diag_output (MU_DIAG_ERROR,
64 _("APOP file %s fails safety check: %s"), 67 _("APOP file %s fails safety check: %s"),
65 APOP_PASSFILE, mu_strerror (rc)); 68 apop_database_name, mu_strerror (rc));
66 mu_dbm_destroy (&db); 69 mu_dbm_destroy (&db);
67 return NULL; 70 return NULL;
68 } 71 }
...@@ -115,20 +118,21 @@ pop3d_apopuser (const char *user) ...@@ -115,20 +118,21 @@ pop3d_apopuser (const char *user)
115 size_t ulen; 118 size_t ulen;
116 FILE *apop_file; 119 FILE *apop_file;
117 120
118 /* FIXME */ 121 rc = mu_file_safety_check (apop_database_name, apop_database_safety,
119 /* if (mu_check_perm (APOP_PASSFILE, 0600)) */ 122 apop_database_uid, NULL);
120 /* { */ 123 if (rc)
121 /* mu_diag_output (MU_DIAG_INFO, */ 124 {
122 /* _("bad permissions on APOP password file")); */ 125 mu_diag_output (MU_DIAG_ERROR,
123 /* return NULL; */ 126 _("APOP file %s fails safety check: %s"),
124 /* } */ 127 apop_database_name, mu_strerror (rc));
125 128 return NULL;
126 apop_file = fopen (APOP_PASSFILE, "r"); 129 }
130 apop_file = fopen (apop_database_name, "r");
127 if (apop_file == NULL) 131 if (apop_file == NULL)
128 { 132 {
129 mu_diag_output (MU_DIAG_INFO, 133 mu_diag_output (MU_DIAG_INFO,
130 _("unable to open APOP password file %s: %s"), 134 _("unable to open APOP password file %s: %s"),
131 APOP_PASSFILE, mu_strerror (errno)); 135 apop_database_name, mu_strerror (errno));
132 return NULL; 136 return NULL;
133 } 137 }
134 138
......
...@@ -31,6 +31,9 @@ int pop3d_transcript; ...@@ -31,6 +31,9 @@ int pop3d_transcript;
31 int debug_mode; 31 int debug_mode;
32 int tls_required; 32 int tls_required;
33 int pop3d_xlines; 33 int pop3d_xlines;
34 char *apop_database_name = APOP_PASSFILE;
35 int apop_database_safety;
36 int apop_database_safety_set;
34 37
35 #ifdef WITH_TLS 38 #ifdef WITH_TLS
36 int tls_available; 39 int tls_available;
...@@ -77,6 +80,22 @@ cb_bulletin_source (void *data, mu_config_value_t *val) ...@@ -77,6 +80,22 @@ cb_bulletin_source (void *data, mu_config_value_t *val)
77 return 0; 80 return 0;
78 } 81 }
79 82
83 static int
84 cb2_file_safety_checks (const char *name, void *data)
85 {
86 if (mu_file_safety_compose (data, name, MU_FILE_SAFETY_ALL))
87 mu_error (_("unknown keyword: %s"), name);
88 return 0;
89 }
90
91 static int
92 cb_apop_safety_checks (void *data, mu_config_value_t *arg)
93 {
94 apop_database_safety_set = 1;
95 return mu_cfg_string_value_cb (arg, cb2_file_safety_checks,
96 &apop_database_safety);
97 }
98
80 #ifdef ENABLE_DBM 99 #ifdef ENABLE_DBM
81 static int 100 static int
82 cb_bulletin_db (void *data, mu_config_value_t *val) 101 cb_bulletin_db (void *data, mu_config_value_t *val)
...@@ -98,6 +117,24 @@ static struct mu_cfg_param pop3d_cfg_param[] = { ...@@ -98,6 +117,24 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
98 N_("Delete expired messages upon closing the mailbox.") }, 117 N_("Delete expired messages upon closing the mailbox.") },
99 { "scan-lines", mu_cfg_bool, &pop3d_xlines, 0, NULL, 118 { "scan-lines", mu_cfg_bool, &pop3d_xlines, 0, NULL,
100 N_("Output the number of lines in the message in its scan listing.") }, 119 N_("Output the number of lines in the message in its scan listing.") },
120 { "apop-database-file", mu_cfg_string, &apop_database_name, 0, NULL,
121 N_("set APOP database file name or URL") },
122 { "apop-database-safety", mu_cfg_callback, NULL, 0, cb_apop_safety_checks,
123 N_("Configure safety checks for APOP database files. Argument is a list or "
124 "sequence of check names optionally prefixed with '+' to enable or "
125 "'-' to disable the corresponding check. Valid check names are:\n"
126 "\n"
127 " none disable all checks\n"
128 " all enable all checks\n"
129 " gwrfil forbid group writable files\n"
130 " awrfil forbid world writable files\n"
131 " grdfil forbid group readable files\n"
132 " ardfil forbid world writable files\n"
133 " linkwrdir forbid symbolic links in group or world writable directories\n"
134 " gwrdir forbid files in group writable directories\n"
135 " awrdir forbid files in world writable directories\n"),
136 N_("arg: list") },
137
101 #ifdef WITH_TLS 138 #ifdef WITH_TLS
102 { "tls-required", mu_cfg_bool, &tls_required, 0, NULL, 139 { "tls-required", mu_cfg_bool, &tls_required, 0, NULL,
103 N_("Always require STLS before entering authentication phase.") }, 140 N_("Always require STLS before entering authentication phase.") },
...@@ -303,6 +340,16 @@ pop3d_alloc_die () ...@@ -303,6 +340,16 @@ pop3d_alloc_die ()
303 pop3d_abquit (ERR_NO_MEM); 340 pop3d_abquit (ERR_NO_MEM);
304 } 341 }
305 342
343 #ifdef ENABLE_DBM
344 static void
345 set_dbm_safety ()
346 {
347 mu_url_t hints = mu_dbm_get_hint ();
348 const char *param[] = { "+all" };
349 mu_url_add_param (hints, 1, param);
350 }
351 #endif
352
306 int 353 int
307 main (int argc, char **argv) 354 main (int argc, char **argv)
308 { 355 {
...@@ -341,6 +388,10 @@ main (int argc, char **argv) ...@@ -341,6 +388,10 @@ main (int argc, char **argv)
341 388
342 mu_log_syslog = 1; 389 mu_log_syslog = 1;
343 manlock_mandatory_locking = 1; 390 manlock_mandatory_locking = 1;
391
392 #ifdef ENABLE_DBM
393 set_dbm_safety ();
394 #endif
344 395
345 if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param, 396 if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param,
346 argc, argv, 0, NULL, server)) 397 argc, argv, 0, NULL, server))
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
36 #define APOP_PASSFILE_NAME "apop" 36 #define APOP_PASSFILE_NAME "apop"
37 37
38 #ifdef ENABLE_DBM 38 #ifdef ENABLE_DBM
39 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME 39 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME ".db"
40 # define ENABLE_LOGIN_DELAY 40 # define ENABLE_LOGIN_DELAY
41 #else 41 #else
42 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME ".passwd" 42 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME ".passwd"
...@@ -197,6 +197,9 @@ extern unsigned int idle_timeout; ...@@ -197,6 +197,9 @@ extern unsigned int idle_timeout;
197 extern int pop3d_transcript; 197 extern int pop3d_transcript;
198 extern size_t pop3d_output_bufsize; 198 extern size_t pop3d_output_bufsize;
199 extern int pop3d_xlines; 199 extern int pop3d_xlines;
200 extern char *apop_database_name;
201 extern int apop_database_safety;
202 extern int apop_database_safety_set;
200 203
201 extern pop3d_command_handler_t pop3d_find_command (const char *name); 204 extern pop3d_command_handler_t pop3d_find_command (const char *name);
202 205
......