Commit afda9ba4 afda9ba46c7eb2c061f3907dc7e80ae1ba38157b by Sergey Poznyakoff

Rewrite TLS support

The new implementation allows for per-server certificates.

* libmu_auth/Makefile.am: Build tls support depending on the value of
MU_COND_GNUTLS.
* libmu_auth/notls.c: New file.
* libmu_auth/tls.c: Rewrite.
* libmu_auth/tlsiostr.c: New file.
* libmu_auth/tlsvar.c: New file.
* libmu_auth/tlsconf.c: New file.

* include/mailutils/sys/tls-stream.h (_mu_tls_stream): New members:
session_type, conf, cred.
(mu_tls_io_stream_create): New proto.
* include/mailutils/tls.h (mu_tls_module_config): Remove definition.
(mu_tls_config): New structure.
(mu_tls_server_stream_create): Remove proto.
(mu_tls_cert_file_checks)
(mu_tls_key_file_checksr)
(mu_tls_ca_file_checks): New globals
(MU_TLS_CERT_FILE_CHECKS)
(MU_TLS_KEY_FILE_CHECKS)
(MU_TLS_CA_FILE_CHECKS): New defines.
(mu_tls_stream_create): New proto.
(mu_tls_config_status): New constants.
(mu_tls_check_config): Remove.
(mu_tls_config_check): New function.

* include/mailutils/server.h (mu_m_server_preflight_fp): New typedef.
(mu_m_server_set_preflight): New proto.

* libmailutils/diag/debcat (tls): New category.
* libmailutils/server/ipsrv.c (mu_ip_server_get_data): New function.
* libmailutils/server/msrv.c (_mu_m_server) <preflight>: New method.
(mu_m_server_set_preflight): New function.
(mu_m_server_destroy): Destroy the srvlist.
(open_connection): New function.
(mu_m_server_run): Remove from srvlist only those servers that failed
to open.  Run preflight check, if registered.

* include/mailutils/cfg.h (mu_cfg_section): New member: data.
* libmailutils/cfg/driver.c (dup_container): Copy the "data" pointer.
(mu_cfg_section_add_params): Preserve original pointer and offset when
necessary.
* libmailutils/cfg/parser.y (_scan_tree_helper): Use the section data
pointer (if set) as data target.

* configure.ac (MU_COND_GNUTLS): New conditional.
* imap4d/commands.c: Remove #ifdef WITH_TLS preprocessor conditional.
* imap4d/imap4d.c (tls_mode): Remove variable.
(imap4d_srv_config): Move definition to the header file.
Remove #ifdef WITH_TLS preprocessor conditionals.
Rename the tls configuration statement to tls-mode.
Add new subsection .server.tls;
Remove the legacy tls-required configuration statement.
(imap4d_mainloop): Change signature: take a pointer to the
struct imap4d_srv_config as the 3rd argument,
Use the cfg->tls_mode member to decide on TLS state.
(main): Call mu_tls_cfg_init.
Install server preflight checker.
* imap4d/imap4d.h: Remove #ifdef WITH_TLS preprocessor conditionals.
(imap4d_srv_config): Moved from imap4d.c
New member: tls_conf
(imap4d_session): New member: tls_conf
(global_tls_conf): New global.
(io_setio, imap4d_init_tls_server): Change prototypes.
* imap4d/io.c (io_setio): Change signature: take a pointer to the
struct mu_tls_config as the 3rd argument.
Rewrite TLS support.
(imap4d_init_tls_server): Take a pointer to the
struct mu_tls_config.
* imap4d/starttls.c (tls_available, tls_done): Remove globals.
(global_tls_conf): New global.
(imap4d_starttls): Keep TLS state in the session.
(tls_encryption_on): Likewise.
(starttls_init): Rewrite as a mserver preflight check function.

* pop3d/capa.c: Remove #ifdef WITH_TLS preprocessor conditional.
(capa_stls): Rewrite.
* pop3d/cmd.c (global_tls_conf): New global.
(stls_preflight): New function.
(pop3d_error_string): Rewrite using char ** array.
* pop3d/extra.c (pop3d_setio): Take a pointer to struct mu_tls_config
as the 3rd argument. Decide on TLS using it.
(pop3d_init_tls_server): Take a pointer to struct mu_tls_config.
* pop3d/pop3d.c: Rename the tls configuration statement to tls-mode.
Add new subsection .server.tls;
Remove the legacy tls-required configuration statement.
(pop3d_mainloop) Take a pointer to struct mu_tls_config
as the 3rd argument. Decide on TLS using it.
(main): Call mu_tls_cfg_init. Install server preflight check.
* pop3d/pop3d.h (pop3d_session): New member tls_conf.
(pop3d_srv_config): New definition.
(global_tls_conf): New extern.
* pop3d/stls.c: Rewrite TLS support.

* NEWS: Document new features.
* configure.ac: Version 3.2.90.
* doc/texinfo/programs.texi: Update.
1 parent 0c8e5985
1 GNU mailutils NEWS -- history of user-visible changes. 2017-03-11 1 GNU mailutils NEWS -- history of user-visible changes. 2017-03-18
2 Copyright (C) 2002-2017 Free Software Foundation, Inc. 2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
5 Please send mailutils bug reports to <bug-mailutils@gnu.org>. 5 Please send mailutils bug reports to <bug-mailutils@gnu.org>.
6 6
7 7
8 Version 3.2.90 (Git)
9
10 * TLS configuration
11
12 Note the following changes to the TLS configuration:
13
14 ** global tls section
15
16 The following statements have been renamed:
17
18 ssl-cafile renamed to ssl-ca-file
19 ssl-cert renamed to ssl-certificate-file
20 ssl-key renamed to ssl-key-file
21
22 The following statements have been removed:
23
24 enable
25 key-file-safety-checks
26 cert-file-safety-checks
27 ca-file-safety-checks
28
29 The functionality of the latter three is now moved to the
30 tls-file-checks section.
31
32 Example of a valid global tls section:
33
34 tls {
35 ssl-certificate-file /etc/ssl/cert/imap.pem;
36 ssl-key-file /etc/ssl/private/imap.key;
37 }
38
39 ** global tls-file-checks statement
40
41 The tls-file-checks statement configures safety checks for SSL
42 certificate and key files. It is a global section. Its syntax is
43 as follows:
44
45 tls-file-checks {
46 key-file <arg: list>;
47 cert-file <arg: list>;
48 ca-file <arg: list>;
49 }
50
51 The <arg> list is a list or sequence of check names optionally
52 prefixed with '+' to enable or '-' to disable the corresponding check.
53 Valid check names are the same as in previous versions.
54
55 Use this statement instead of the deprecated cert-file-safety-checks,
56 key-file-safety-checks, and ca-file-safety-checks.
57
58 * Per-server TLS support
59
60 It is now possible to configure per-server SSL certificates in POP3
61 and IMAP4 servers. To do so, place a "tls" subsection within the
62 corresponding "server" section. The syntax of the "tls" subsection
63 is the same as for the global section described above, e.g.:
64
65 server imap.example.com:143 {
66 tls-mode required;
67 tls {
68 ssl-certificate-file /etc/ssl/cert/imap.pem;
69 ssl-key-file /etc/ssl/private/imap.key;
70 }
71 }
72
73 If the "tls" section is absent, but "tls-mode" is specified and it's
74 value is anything but "no", the settings from the global "tls" section
75 will be used. Im this case, it is an error if the global "tls"
76 section is not defined.
77
78
8 Version 3.2 - 2017-03-11 79 Version 3.2 - 2017-03-11
9 80
10 * configuration syntax 81 * configuration syntax
......
...@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along ...@@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License along
16 dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. 16 dnl with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
17 17
18 AC_PREREQ(2.63) 18 AC_PREREQ(2.63)
19 AC_INIT([GNU Mailutils], [3.2], [bug-mailutils@gnu.org], [mailutils], 19 AC_INIT([GNU Mailutils], [3.2.90], [bug-mailutils@gnu.org], [mailutils],
20 [http://mailutils.org]) 20 [http://mailutils.org])
21 AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c]) 21 AC_CONFIG_SRCDIR([libmailutils/mailbox/mailbox.c])
22 AC_CONFIG_AUX_DIR([build-aux]) 22 AC_CONFIG_AUX_DIR([build-aux])
...@@ -306,6 +306,7 @@ MU_CHECK_GNUTLS([1.2.1],[ ...@@ -306,6 +306,7 @@ MU_CHECK_GNUTLS([1.2.1],[
306 ],[ 306 ],[
307 status_gnutls=no 307 status_gnutls=no
308 ]) 308 ])
309 AM_CONDITIONAL([MU_COND_GNUTLS], [test "$status_gnutls" = yes])
309 310
310 AC_SUBST(SITE_MAIL_RC) 311 AC_SUBST(SITE_MAIL_RC)
311 AC_ARG_WITH([mail-rc], 312 AC_ARG_WITH([mail-rc],
......
...@@ -417,6 +417,7 @@ configuration files. ...@@ -417,6 +417,7 @@ configuration files.
417 * sql statement:: 417 * sql statement::
418 * ldap statement:: 418 * ldap statement::
419 * tls statement:: 419 * tls statement::
420 * tls-file-checks statement::
420 * gsasl statement:: 421 * gsasl statement::
421 @end menu 422 @end menu
422 423
...@@ -1700,8 +1701,19 @@ server @var{ipaddr}[:@var{port}] @{ ...@@ -1700,8 +1701,19 @@ server @var{ipaddr}[:@var{port}] @{
1700 backlog <number: callback>; 1701 backlog <number: callback>;
1701 1702
1702 # @r{Kind of TLS encryption to use for this server.} 1703 # @r{Kind of TLS encryption to use for this server.}
1703 tls @samp{no}|@samp{ondemand}|@samp{required}|@samp{connection}; 1704 tls-mode @samp{no}|@samp{ondemand}|@samp{required}|@samp{connection};
1704 1705
1706 tls @{
1707 # @r{Specify SSL certificate file.}
1708 ssl-certificate-file @var{string};
1709 # @r{Specify SSL certificate key file.}
1710 ssl-key-file @var{file};
1711 # @r{Specify trusted CAs file.}
1712 ssl-ca-file @var{file};
1713 # @r{Set the priorities to use on the ciphers, methods, etc.}
1714 ssl-priorities @var{string};
1715 @}
1716
1705 # @r{Set server specific ACLs.} 1717 # @r{Set server specific ACLs.}
1706 acl @{ /* @xref{ACL Statement}. */ @}; 1718 acl @{ /* @xref{ACL Statement}. */ @};
1707 @} 1719 @}
...@@ -1756,7 +1768,7 @@ settings (@pxref{General Server Configuration, timeout}). ...@@ -1756,7 +1768,7 @@ settings (@pxref{General Server Configuration, timeout}).
1756 Configures the size of the queue of pending connections 1768 Configures the size of the queue of pending connections
1757 @end deffn 1769 @end deffn
1758 1770
1759 @deffn {Configuration} tls @var{mode}; 1771 @deffn {Configuration} tls-mode @var{mode};
1760 Configure the use of TLS encryption. The @var{mode} argument is one 1772 Configure the use of TLS encryption. The @var{mode} argument is one
1761 of the following: 1773 of the following:
1762 1774
...@@ -1781,6 +1793,20 @@ TLS is always forced when the connection is established. For ...@@ -1781,6 +1793,20 @@ TLS is always forced when the connection is established. For
1781 @end table 1793 @end table
1782 @end deffn 1794 @end deffn
1783 1795
1796 @deffn {Configuration} tls @{ ... @}
1797 The @code{tls} statement configures SSL certificate and key files, as
1798 well as other SSL settings for use in this server. It is used when
1799 @code{tls-mode} is set to any of the following values:
1800 @code{ondemand}, @code{required}, @code{connection}.
1801
1802 If @code{tls-mode} is set to any of the values above and @code{tls}
1803 section is absent, settings from the global @code{tls} section will
1804 be used. In this case, it is an error if the global @code{tls}
1805 section is not defined.
1806
1807 @xref{tls statement}, for a discussion of its syntax.
1808 @end deffn
1809
1784 @deffn {Configuration} acl 1810 @deffn {Configuration} acl
1785 This statement defines a per-server Access Control List. Its syntax 1811 This statement defines a per-server Access Control List. Its syntax
1786 is as described in @ref{ACL Statement}. Per-server ACLs complement, 1812 is as described in @ref{ACL Statement}. Per-server ACLs complement,
...@@ -2483,39 +2509,32 @@ default filter is: ...@@ -2483,39 +2509,32 @@ default filter is:
2483 @subheading Syntax 2509 @subheading Syntax
2484 @example 2510 @example
2485 tls @{ 2511 tls @{
2486 # @r{Enable TLS support.}
2487 enable @var{bool};
2488 # @r{Specify SSL certificate file.} 2512 # @r{Specify SSL certificate file.}
2489 ssl-cert @var{string}; 2513 ssl-certificate-file @var{string};
2490 # @r{Specify SSL certificate key file.} 2514 # @r{Specify SSL certificate key file.}
2491 ssl-key @var{file}; 2515 ssl-key-file @var{file};
2492 # @r{Specify trusted CAs file.} 2516 # @r{Specify trusted CAs file.}
2493 ssl-cafile @var{file}; 2517 ssl-ca-file @var{file};
2494 # @r{Set the priorities to use on the ciphers, methods, etc.} 2518 # @r{Set the priorities to use on the ciphers, methods, etc.}
2495 ssl-priorities @var{string}; 2519 ssl-priorities @var{string};
2496 # @r{Configure safety checks for SSL key file.}
2497 key-file-safety-checks @var{list};
2498 # @r{Configure safety checks for SSL certificate.}
2499 cert-file-safety-checks @var{list};
2500 # @r{Configure safety checks for SSL CA file.}
2501 ca-file-safety-checks @var{list};
2502 @} 2520 @}
2503 @end example 2521 @end example
2504 @subheading Description 2522 @subheading Description
2505 2523
2506 @deffn {Configuration} enable @var{bool} 2524 The @samp{tls} statement configures TLS parameters to be used by
2507 Enable TLS support. If absent, @samp{enable On} is assumed. 2525 servers. It can appear both in the global scope and in server
2508 @end deffn 2526 scope. Global tls settings are applied for servers that are declared
2527 as supporting TLS encryption, but lack the @samp{tls} substatement.
2509 2528
2510 @deffn {Configuration} ssl-cert @var{string} 2529 @deffn {Configuration} ssl-certificate-file @var{string}
2511 Specify SSL certificate file. 2530 Specify SSL certificate file.
2512 @end deffn 2531 @end deffn
2513 2532
2514 @deffn {Configuration} ssl-key @var{file} 2533 @deffn {Configuration} ssl-key-file @var{file}
2515 Specify SSL certificate key file. 2534 Specify SSL certificate key file.
2516 @end deffn 2535 @end deffn
2517 2536
2518 @deffn {Configuration} ssl-cafile @var{file} 2537 @deffn {Configuration} ssl-ca-file @var{file}
2519 Specify the trusted certificate authorities file. 2538 Specify the trusted certificate authorities file.
2520 @end deffn 2539 @end deffn
2521 2540
...@@ -2524,7 +2543,27 @@ Set the priorities to use on the ciphers, key exchange methods, MACs ...@@ -2524,7 +2543,27 @@ Set the priorities to use on the ciphers, key exchange methods, MACs
2524 and compression methods. 2543 and compression methods.
2525 @end deffn 2544 @end deffn
2526 2545
2527 @deffn {Configuration} key-file-safety-checks @var{list} 2546 @node tls-file-checks statement
2547 @subsection The @code{tls-file-checks} Statement
2548 @kwindex tls-file-checks
2549 @subheading Syntax
2550 @example
2551 tls-file-checks @{
2552 # @r{Configure safety checks for SSL key file.}
2553 key-file @var{list};
2554 # @r{Configure safety checks for SSL certificate.}
2555 cert-file @var{list};
2556 # @r{Configure safety checks for SSL CA file.}
2557 ca-file @var{list};
2558 @}
2559 @end example
2560
2561 @subheading Description
2562
2563 This section configures security checks applied to the particular SSL
2564 configuration files in order to decide whether it is safe to use them.
2565
2566 @deffn {Configuration} key-file @var{list}
2528 Configure safety checks for SSL key file. Elements of the @var{list} are 2567 Configure safety checks for SSL key file. Elements of the @var{list} are
2529 names of individual checks, optionally prefixed with @samp{+} to enable or 2568 names of individual checks, optionally prefixed with @samp{+} to enable or
2530 @samp{-} to disable the corresponding check. Valid check names are: 2569 @samp{-} to disable the corresponding check. Valid check names are:
...@@ -2551,16 +2590,17 @@ Forbid files in world writable directories, ...@@ -2551,16 +2590,17 @@ Forbid files in world writable directories,
2551 @end table 2590 @end table
2552 @end deffn 2591 @end deffn
2553 2592
2554 @deffn {Configuration} cert-file-safety-checks @var{list} 2593 @deffn {Configuration} cert-file @var{list}
2555 Configure safety checks for SSL certificate. See 2594 Configure safety checks for SSL certificate. See
2556 @code{key-file-safety-checks} for a description of @var{list}. 2595 @code{key-file} for a description of @var{list}.
2557 @end deffn 2596 @end deffn
2558 2597
2559 @deffn {Configuration} ca-file-safety-checks @var{list} 2598 @deffn {Configuration} ca-file @var{list}
2560 Configure safety checks for SSL CA file. See 2599 Configure safety checks for SSL CA file. See
2561 @code{key-file-safety-checks} for a description of @var{list}. 2600 @code{key-file} for a description of @var{list}.
2562 @end deffn 2601 @end deffn
2563 2602
2603
2564 @node gsasl statement 2604 @node gsasl statement
2565 @subsection The @code{gsasl} Statement 2605 @subsection The @code{gsasl} Statement
2566 @anchor{GSASL Statement} 2606 @anchor{GSASL Statement}
...@@ -7494,6 +7534,7 @@ The following configuration file statements affect the behavior of ...@@ -7494,6 +7534,7 @@ The following configuration file statements affect the behavior of
7494 @headitem Statement @tab Reference 7534 @headitem Statement @tab Reference
7495 @item debug @tab @xref{debug statement}. 7535 @item debug @tab @xref{debug statement}.
7496 @item tls @tab @xref{tls statement}. 7536 @item tls @tab @xref{tls statement}.
7537 @item tls-file-checks @tab @xref{tls-file-checks statement}.
7497 @item mailbox @tab @xref{mailbox statement}. 7538 @item mailbox @tab @xref{mailbox statement}.
7498 @item locking @tab @xref{locking statement}. 7539 @item locking @tab @xref{locking statement}.
7499 @item logging @tab @xref{logging statement}. 7540 @item logging @tab @xref{logging statement}.
...@@ -7804,6 +7845,7 @@ configuration statements: ...@@ -7804,6 +7845,7 @@ configuration statements:
7804 @headitem Statement @tab Reference 7845 @headitem Statement @tab Reference
7805 @item debug @tab @xref{debug statement}. 7846 @item debug @tab @xref{debug statement}.
7806 @item tls @tab @xref{tls statement}. 7847 @item tls @tab @xref{tls statement}.
7848 @item tls-file-checks @tab @xref{tls-file-checks statement}.
7807 @item mailbox @tab @xref{mailbox statement}. 7849 @item mailbox @tab @xref{mailbox statement}.
7808 @item locking @tab @xref{locking statement}. 7850 @item locking @tab @xref{locking statement}.
7809 @item logging @tab @xref{logging statement}. 7851 @item logging @tab @xref{logging statement}.
......
...@@ -47,8 +47,6 @@ struct imap4d_command imap4d_command_table [] = ...@@ -47,8 +47,6 @@ struct imap4d_command imap4d_command_table [] =
47 { "NAMESPACE", imap4d_namespace, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 47 { "NAMESPACE", imap4d_namespace, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
48 { "ID", imap4d_id, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 48 { "ID", imap4d_id, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
49 { "IDLE", imap4d_idle, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 49 { "IDLE", imap4d_idle, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
50 #ifdef WITH_TLS
51 { "STARTTLS", imap4d_starttls, STATE_NONAUTH, STATE_NONE, STATE_NONE, NULL }, 50 { "STARTTLS", imap4d_starttls, STATE_NONAUTH, STATE_NONE, STATE_NONE, NULL },
52 #endif /* WITH_TLS */
53 { NULL, 0, 0, 0, 0, NULL } 51 { NULL, 0, 0, 0, 0, NULL }
54 }; 52 };
......
...@@ -30,7 +30,6 @@ char *real_homedir; /* Homedir as returned by user database */ ...@@ -30,7 +30,6 @@ char *real_homedir; /* Homedir as returned by user database */
30 int state = STATE_NONAUTH; /* Current IMAP4 state */ 30 int state = STATE_NONAUTH; /* Current IMAP4 state */
31 struct mu_auth_data *auth_data; 31 struct mu_auth_data *auth_data;
32 32
33 enum tls_mode tls_mode;
34 int login_disabled; /* Disable LOGIN command */ 33 int login_disabled; /* Disable LOGIN command */
35 int create_home_dir; /* Create home directory if it does not 34 int create_home_dir; /* Create home directory if it does not
36 exist */ 35 exist */
...@@ -258,13 +257,6 @@ cb_group (void *data, mu_config_value_t *arg) ...@@ -258,13 +257,6 @@ cb_group (void *data, mu_config_value_t *arg)
258 } 257 }
259 258
260 259
261 struct imap4d_srv_config
262 {
263 struct mu_srv_config m_cfg;
264 enum tls_mode tls_mode;
265 };
266
267 #ifdef WITH_TLS
268 static int 260 static int
269 cb_tls (void *data, mu_config_value_t *val) 261 cb_tls (void *data, mu_config_value_t *val)
270 { 262 {
...@@ -293,33 +285,6 @@ cb_tls (void *data, mu_config_value_t *val) ...@@ -293,33 +285,6 @@ cb_tls (void *data, mu_config_value_t *val)
293 mu_error (_("not a valid tls keyword: %s"), val->v.string); 285 mu_error (_("not a valid tls keyword: %s"), val->v.string);
294 return 0; 286 return 0;
295 } 287 }
296 #endif
297
298 #ifdef WITH_TLS
299 static int
300 cb_tls_required (void *data, mu_config_value_t *val)
301 {
302 int bv;
303
304 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
305 return 1;
306 if (mu_str_to_c (val->v.string, mu_c_bool, &bv, NULL))
307 mu_error (_("Not a boolean value"));
308 else if (bv)
309 {
310 tls_mode = tls_required;
311 mu_diag_output (MU_DIAG_WARNING,
312 "the \"tls-required\" statement is deprecated, "
313 "use \"tls required\" instead");
314 }
315 else
316 mu_diag_output (MU_DIAG_WARNING,
317 "the \"tls-required\" statement is deprecated, "
318 "use \"tls\" instead");
319
320 return 0;
321 }
322 #endif
323 288
324 static mu_list_t auth_deny_user_list, auth_allow_user_list; 289 static mu_list_t auth_deny_user_list, auth_allow_user_list;
325 static mu_list_t auth_deny_group_list, auth_allow_group_list; 290 static mu_list_t auth_deny_group_list, auth_allow_group_list;
...@@ -532,13 +497,13 @@ namespace_cfg_init (void) ...@@ -532,13 +497,13 @@ namespace_cfg_init (void)
532 } 497 }
533 498
534 static struct mu_cfg_param imap4d_srv_param[] = { 499 static struct mu_cfg_param imap4d_srv_param[] = {
535 #ifdef WITH_TLS 500 { "tls-mode", mu_cfg_callback,
536 { "tls", mu_cfg_callback,
537 NULL, mu_offsetof (struct imap4d_srv_config, tls_mode), cb_tls, 501 NULL, mu_offsetof (struct imap4d_srv_config, tls_mode), cb_tls,
538 N_("Kind of TLS encryption to use for this server"), 502 N_("Kind of TLS encryption to use for this server"),
539 /* TRANSLATORS: translate only arg:, the rest are keywords */ 503 /* TRANSLATORS: translate only arg:, the rest are keywords */
540 N_("arg: false|true|ondemand|stls|requred|connection") }, 504 N_("arg: false|true|ondemand|stls|requred|connection") },
541 #endif 505 { "tls", mu_cfg_section,
506 NULL, mu_offsetof (struct imap4d_srv_config, tls_conf) },
542 { NULL } 507 { NULL }
543 }; 508 };
544 509
...@@ -568,16 +533,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -568,16 +533,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
568 { "retain-groups", mu_cfg_callback, &user_retain_groups, 0, cb_group, 533 { "retain-groups", mu_cfg_callback, &user_retain_groups, 0, cb_group,
569 N_("Retain these supplementary groups when switching to user privileges"), 534 N_("Retain these supplementary groups when switching to user privileges"),
570 N_("groups: list of string") }, 535 N_("groups: list of string") },
571 #ifdef WITH_TLS 536 { "tls", mu_cfg_section, &global_tls_conf },
572 { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls,
573 N_("Kind of TLS encryption to use"),
574 /* TRANSLATORS: translate only arg:, the rest are keywords */
575 N_("arg: false|true|ondemand|stls|requred|connection") },
576 { "tls-required", mu_cfg_callback, &tls_mode, 0, cb_tls_required,
577 N_("Always require STLS before entering authentication phase.\n"
578 "Deprecated, use \"tls required\" instead."),
579 N_("arg: bool") },
580 #endif
581 { "preauth", mu_cfg_callback, NULL, 0, cb_preauth, 537 { "preauth", mu_cfg_callback, NULL, 0, cb_preauth,
582 N_("Configure PREAUTH mode. <value> is one of:\n" 538 N_("Configure PREAUTH mode. <value> is one of:\n"
583 " prog:///<full-program-name: string>\n" 539 " prog:///<full-program-name: string>\n"
...@@ -836,7 +792,7 @@ imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo)) ...@@ -836,7 +792,7 @@ imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo))
836 } 792 }
837 793
838 static int 794 static int
839 imap4d_mainloop (int ifd, int ofd, enum tls_mode tls) 795 imap4d_mainloop (int ifd, int ofd, struct imap4d_srv_config *cfg)
840 { 796 {
841 imap4d_tokbuf_t tokp; 797 imap4d_tokbuf_t tokp;
842 char *text; 798 char *text;
...@@ -877,33 +833,27 @@ imap4d_mainloop (int ifd, int ofd, enum tls_mode tls) ...@@ -877,33 +833,27 @@ imap4d_mainloop (int ifd, int ofd, enum tls_mode tls)
877 /* Set child-specific signal handlers */ 833 /* Set child-specific signal handlers */
878 imap4d_child_signal_setup (imap4d_child_signal); 834 imap4d_child_signal_setup (imap4d_child_signal);
879 } 835 }
880
881 if (tls == tls_unspecified)
882 tls = tls_available ? tls_ondemand : tls_no;
883 else if (tls != tls_no && !tls_available)
884 {
885 mu_error (_("TLS is not configured, but requested in the "
886 "configuration"));
887 tls = tls_no;
888 }
889 836
890 switch (tls) 837 switch (cfg->tls_mode)
891 { 838 {
892 case tls_required: 839 case tls_required:
893 imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED); 840 imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED);
841 imap4d_capability_add (IMAP_CAPA_STARTTLS);
894 break; 842 break;
895 case tls_no: 843
896 imap4d_capability_remove (IMAP_CAPA_STARTTLS); 844 case tls_ondemand:
897 tls_available = 0; 845 imap4d_capability_add (IMAP_CAPA_STARTTLS);
898 break; 846 break;
847
899 default: 848 default:
900 break; 849 break;
901 } 850 }
902 851
903 session.tls_mode = tls; 852 session.tls_mode = cfg->tls_mode;
853 session.tls_conf = &cfg->tls_conf;
904 854
905 io_setio (ifd, ofd, tls == tls_connection); 855 io_setio (ifd, ofd, cfg->tls_mode == tls_connection ? &cfg->tls_conf : NULL);
906 if (tls == tls_connection) 856 if (cfg->tls_mode == tls_connection)
907 tls_encryption_on (&session); 857 tls_encryption_on (&session);
908 858
909 if (imap4d_preauth_setup (ifd) == 0) 859 if (imap4d_preauth_setup (ifd) == 0)
...@@ -961,8 +911,7 @@ imap4d_connection (int fd, struct sockaddr *sa, int salen, ...@@ -961,8 +911,7 @@ imap4d_connection (int fd, struct sockaddr *sa, int salen,
961 else 911 else
962 rc = 1; 912 rc = 1;
963 913
964 imap4d_mainloop (fd, fd, 914 imap4d_mainloop (fd, fd, cfg);
965 cfg->tls_mode == tls_unspecified ? tls_mode : cfg->tls_mode);
966 915
967 if (rc == 0) 916 if (rc == 0)
968 clr_strerr_flt (); 917 clr_strerr_flt ();
...@@ -1040,8 +989,9 @@ main (int argc, char **argv) ...@@ -1040,8 +989,9 @@ main (int argc, char **argv)
1040 mu_tcpwrapper_cfg_init (); 989 mu_tcpwrapper_cfg_init ();
1041 manlock_cfg_init (); 990 manlock_cfg_init ();
1042 mu_acl_cfg_init (); 991 mu_acl_cfg_init ();
992 mu_tls_cfg_init ();
1043 namespace_cfg_init (); 993 namespace_cfg_init ();
1044 994
1045 mu_m_server_create (&server, program_version); 995 mu_m_server_create (&server, program_version);
1046 mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config)); 996 mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config));
1047 mu_m_server_set_conn (server, imap4d_connection); 997 mu_m_server_set_conn (server, imap4d_connection);
...@@ -1141,9 +1091,7 @@ main (int argc, char **argv) ...@@ -1141,9 +1091,7 @@ main (int argc, char **argv)
1141 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ 1091 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
1142 1092
1143 /* Check TLS environment, i.e. cert and key files */ 1093 /* Check TLS environment, i.e. cert and key files */
1144 #ifdef WITH_TLS 1094 mu_m_server_set_preflight (server, starttls_init);
1145 starttls_init ();
1146 #endif /* WITH_TLS */
1147 1095
1148 /* Actually run the daemon. */ 1096 /* Actually run the daemon. */
1149 if (mu_m_server_mode (server) == MODE_DAEMON) 1097 if (mu_m_server_mode (server) == MODE_DAEMON)
...@@ -1155,9 +1103,12 @@ main (int argc, char **argv) ...@@ -1155,9 +1103,12 @@ main (int argc, char **argv)
1155 } 1103 }
1156 else 1104 else
1157 { 1105 {
1106 struct imap4d_srv_config cfg;
1107 memset (&cfg, 0, sizeof cfg);
1108 cfg.tls_mode = tls_no;
1158 /* Make sure we are in the root directory. */ 1109 /* Make sure we are in the root directory. */
1159 chdir ("/"); 1110 chdir ("/");
1160 status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_mode); 1111 status = imap4d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, &cfg);
1161 } 1112 }
1162 1113
1163 if (status) 1114 if (status)
......
...@@ -193,6 +193,14 @@ enum tls_mode ...@@ -193,6 +193,14 @@ enum tls_mode
193 struct imap4d_session 193 struct imap4d_session
194 { 194 {
195 enum tls_mode tls_mode; 195 enum tls_mode tls_mode;
196 struct mu_tls_config *tls_conf;
197 };
198
199 struct imap4d_srv_config
200 {
201 struct mu_srv_config m_cfg;
202 enum tls_mode tls_mode;
203 struct mu_tls_config tls_conf;
196 }; 204 };
197 205
198 extern struct imap4d_command imap4d_command_table[]; 206 extern struct imap4d_command imap4d_command_table[];
...@@ -217,7 +225,8 @@ extern mu_list_t imap4d_id_list; ...@@ -217,7 +225,8 @@ extern mu_list_t imap4d_id_list;
217 extern int imap4d_argc; 225 extern int imap4d_argc;
218 extern char **imap4d_argv; 226 extern char **imap4d_argv;
219 extern jmp_buf child_jmp; 227 extern jmp_buf child_jmp;
220 228 extern struct mu_tls_config global_tls_conf;
229
221 extern int test_mode; 230 extern int test_mode;
222 extern int silent_expunge; 231 extern int silent_expunge;
223 232
...@@ -240,7 +249,7 @@ extern int io_stream_completion_response (mu_stream_t str, ...@@ -240,7 +249,7 @@ extern int io_stream_completion_response (mu_stream_t str,
240 const char *format, ...) 249 const char *format, ...)
241 MU_PRINTFLIKE(4,5); 250 MU_PRINTFLIKE(4,5);
242 void io_getline (char **pbuf, size_t *psize, size_t *pnbytes); 251 void io_getline (char **pbuf, size_t *psize, size_t *pnbytes);
243 void io_setio (int, int, int); 252 void io_setio (int, int, struct mu_tls_config *);
244 void io_flush (void); 253 void io_flush (void);
245 int io_wait_input (int); 254 int io_wait_input (int);
246 255
...@@ -333,14 +342,10 @@ extern int imap4d_select (struct imap4d_session *, ...@@ -333,14 +342,10 @@ extern int imap4d_select (struct imap4d_session *,
333 struct imap4d_command *, imap4d_tokbuf_t); 342 struct imap4d_command *, imap4d_tokbuf_t);
334 extern int imap4d_select0 (struct imap4d_command *, const char *, int); 343 extern int imap4d_select0 (struct imap4d_command *, const char *, int);
335 extern int imap4d_select_status (void); 344 extern int imap4d_select_status (void);
336 #ifdef WITH_TLS
337 extern int imap4d_starttls (struct imap4d_session *, 345 extern int imap4d_starttls (struct imap4d_session *,
338 struct imap4d_command *, imap4d_tokbuf_t); 346 struct imap4d_command *, imap4d_tokbuf_t);
339 extern void starttls_init (void); 347 int starttls_init (mu_m_server_t msrv);
340 void tls_encryption_on (struct imap4d_session *); 348 void tls_encryption_on (struct imap4d_session *);
341 #else
342 # define tls_encryption_on(s)
343 #endif /* WITH_TLS */
344 extern int imap4d_status (struct imap4d_session *, 349 extern int imap4d_status (struct imap4d_session *,
345 struct imap4d_command *, imap4d_tokbuf_t); 350 struct imap4d_command *, imap4d_tokbuf_t);
346 extern int imap4d_store (struct imap4d_session *, 351 extern int imap4d_store (struct imap4d_session *,
...@@ -466,9 +471,7 @@ int util_trim_nl (char *s, size_t len); ...@@ -466,9 +471,7 @@ int util_trim_nl (char *s, size_t len);
466 471
467 int set_xscript_level (int xlev); 472 int set_xscript_level (int xlev);
468 473
469 #ifdef WITH_TLS 474 int imap4d_init_tls_server (struct mu_tls_config *);
470 int imap4d_init_tls_server (void);
471 #endif /* WITH_TLS */
472 475
473 struct imap4d_auth 476 struct imap4d_auth
474 { 477 {
......
...@@ -50,7 +50,7 @@ log_cipher (mu_stream_t stream) ...@@ -50,7 +50,7 @@ log_cipher (mu_stream_t stream)
50 } 50 }
51 51
52 void 52 void
53 io_setio (int ifd, int ofd, int tls) 53 io_setio (int ifd, int ofd, struct mu_tls_config *tls_conf)
54 { 54 {
55 mu_stream_t str, istream, ostream; 55 mu_stream_t str, istream, ostream;
56 56
...@@ -68,10 +68,12 @@ io_setio (int ifd, int ofd, int tls) ...@@ -68,10 +68,12 @@ io_setio (int ifd, int ofd, int tls)
68 mu_stream_set_buffer (ostream, mu_buffer_line, 0); 68 mu_stream_set_buffer (ostream, mu_buffer_line, 0);
69 69
70 /* Combine the two streams into an I/O one. */ 70 /* Combine the two streams into an I/O one. */
71 #ifdef WITH_TLS 71 if (tls_conf)
72 if (tls)
73 { 72 {
74 int rc = mu_tls_server_stream_create (&str, istream, ostream, 0); 73 int rc = mu_tls_stream_create (&str, istream, ostream,
74 tls_conf,
75 MU_TLS_SERVER,
76 0);
75 if (rc) 77 if (rc)
76 { 78 {
77 mu_stream_unref (istream); 79 mu_stream_unref (istream);
...@@ -81,9 +83,7 @@ io_setio (int ifd, int ofd, int tls) ...@@ -81,9 +83,7 @@ io_setio (int ifd, int ofd, int tls)
81 } 83 }
82 log_cipher (str); 84 log_cipher (str);
83 } 85 }
84 else 86 else if (mu_iostream_create (&str, istream, ostream))
85 #endif
86 if (mu_iostream_create (&str, istream, ostream))
87 imap4d_bye (ERR_STREAM_CREATE); 87 imap4d_bye (ERR_STREAM_CREATE);
88 88
89 /* Convert all writes to CRLF form. 89 /* Convert all writes to CRLF form.
...@@ -120,9 +120,8 @@ io_setio (int ifd, int ofd, int tls) ...@@ -120,9 +120,8 @@ io_setio (int ifd, int ofd, int tls)
120 } 120 }
121 } 121 }
122 122
123 #ifdef WITH_TLS
124 int 123 int
125 imap4d_init_tls_server () 124 imap4d_init_tls_server (struct mu_tls_config *tls_conf)
126 { 125 {
127 mu_stream_t tlsstream, stream[2]; 126 mu_stream_t tlsstream, stream[2];
128 int rc; 127 int rc;
...@@ -135,7 +134,12 @@ imap4d_init_tls_server () ...@@ -135,7 +134,12 @@ imap4d_init_tls_server ()
135 return 1; 134 return 1;
136 } 135 }
137 136
138 rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); 137 rc = mu_tls_stream_create (&tlsstream, stream[0], stream[1],
138 tls_conf,
139 MU_TLS_SERVER,
140 0);
141 mu_stream_unref (stream[0]);
142 mu_stream_unref (stream[1]);
139 if (rc) 143 if (rc)
140 { 144 {
141 mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), 145 mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
...@@ -145,8 +149,6 @@ imap4d_init_tls_server () ...@@ -145,8 +149,6 @@ imap4d_init_tls_server ()
145 149
146 log_cipher (tlsstream); 150 log_cipher (tlsstream);
147 151
148 mu_stream_unref (stream[0]);
149 mu_stream_unref (stream[1]);
150 stream[0] = stream[1] = tlsstream; 152 stream[0] = stream[1] = tlsstream;
151 153
152 rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream); 154 rc = mu_stream_ioctl (iostream, MU_IOCTL_SUBSTREAM, MU_IOCTL_OP_SET, stream);
...@@ -158,11 +160,9 @@ imap4d_init_tls_server () ...@@ -158,11 +160,9 @@ imap4d_init_tls_server ()
158 } 160 }
159 mu_stream_unref (stream[0]); 161 mu_stream_unref (stream[0]);
160 mu_stream_unref (stream[1]); 162 mu_stream_unref (stream[1]);
161 163
162 return 0; 164 return 0;
163 } 165 }
164 #endif
165
166 166
167 /* Status Code to String. */ 167 /* Status Code to String. */
168 static const char * 168 static const char *
......
...@@ -17,11 +17,7 @@ ...@@ -17,11 +17,7 @@
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
20 int tls_available; 20 struct mu_tls_config global_tls_conf;
21
22 #ifdef WITH_TLS
23
24 static int tls_done;
25 21
26 /* 22 /*
27 6.2.1. STARTTLS Command 23 6.2.1. STARTTLS Command
...@@ -39,7 +35,7 @@ imap4d_starttls (struct imap4d_session *session, ...@@ -39,7 +35,7 @@ imap4d_starttls (struct imap4d_session *session,
39 { 35 {
40 int status; 36 int status;
41 37
42 if (!tls_available || tls_done) 38 if (session->tls_mode == tls_no)
43 return io_completion_response (command, RESP_BAD, "Invalid command"); 39 return io_completion_response (command, RESP_BAD, "Invalid command");
44 40
45 if (imap4d_tokbuf_argc (tok) != 2) 41 if (imap4d_tokbuf_argc (tok) != 2)
...@@ -48,7 +44,7 @@ imap4d_starttls (struct imap4d_session *session, ...@@ -48,7 +44,7 @@ imap4d_starttls (struct imap4d_session *session,
48 status = io_completion_response (command, RESP_OK, "Begin TLS negotiation"); 44 status = io_completion_response (command, RESP_OK, "Begin TLS negotiation");
49 io_flush (); 45 io_flush ();
50 46
51 if (imap4d_init_tls_server () == 0) 47 if (imap4d_init_tls_server (session->tls_conf) == 0)
52 tls_encryption_on (session); 48 tls_encryption_on (session);
53 else 49 else
54 { 50 {
...@@ -63,24 +59,101 @@ imap4d_starttls (struct imap4d_session *session, ...@@ -63,24 +59,101 @@ imap4d_starttls (struct imap4d_session *session,
63 void 59 void
64 tls_encryption_on (struct imap4d_session *session) 60 tls_encryption_on (struct imap4d_session *session)
65 { 61 {
66 tls_done = 1; 62 session->tls_mode = tls_no;
67 imap4d_capability_remove (IMAP_CAPA_STARTTLS); 63 imap4d_capability_remove (IMAP_CAPA_STARTTLS);
68 64
69 login_disabled = 0; 65 login_disabled = 0;
70 imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED); 66 imap4d_capability_remove (IMAP_CAPA_LOGINDISABLED);
71 67
72 session->tls_mode = tls_no;
73 imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED); 68 imap4d_capability_remove (IMAP_CAPA_XTLSREQUIRED);
74 } 69 }
75 70
76 void 71 int
77 starttls_init () 72 starttls_init (mu_m_server_t msrv)
78 { 73 {
79 tls_available = mu_check_tls_environment (); 74 mu_list_t srvlist;
80 if (tls_available) 75 mu_iterator_t itr;
81 imap4d_capability_add (IMAP_CAPA_STARTTLS); 76 int errors = 0;
82 } 77 int tls_ok = mu_init_tls_libs ();
78 int tls_requested = 0;
79 int global_conf_status = 0;
80
81 if (global_tls_conf.cert_file)
82 global_conf_status = mu_tls_config_check (&global_tls_conf, 1);
83 else
84 global_conf_status = MU_TLS_CONFIG_NULL;
85
86 mu_m_server_get_srvlist (msrv, &srvlist);
87 mu_list_get_iterator (srvlist, &itr);
88 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
89 {
90 mu_ip_server_t ipsrv;
91 struct imap4d_srv_config *cfg;
92 mu_iterator_current (itr, (void**) &ipsrv);
93 cfg = mu_ip_server_get_data (ipsrv);
94 switch (cfg->tls_mode)
95 {
96 case tls_unspecified:
97 if (cfg->tls_conf.cert_file)
98 {
99 cfg->tls_mode = tls_ondemand;
100 break;
101 }
102 else
103 cfg->tls_mode = tls_no;
104 /* fall through */
105 case tls_no:
106 continue;
107
108 default:
109 break;
110 }
111
112 switch (mu_tls_config_check (&cfg->tls_conf, 1))
113 {
114 case MU_TLS_CONFIG_OK:
115 if (!cfg->tls_conf.cert_file)
116 {
117 mu_error (_("server %s: no certificate set"),
118 mu_ip_server_addrstr (ipsrv));
119 errors = 1;
120 }
121 break;
122
123 case MU_TLS_CONFIG_NULL:
124 if (global_conf_status != MU_TLS_CONFIG_NULL)
125 {
126 cfg->tls_conf = global_tls_conf;
127 }
128 else
129 {
130 mu_error (_("server %s: no certificate set"),
131 mu_ip_server_addrstr (ipsrv));
132 errors = 1;
133 }
134 break;
135
136 default:
137 mu_error (_("server %s: TLS configuration failed"),
138 mu_ip_server_addrstr (ipsrv));
139 errors = 1;
140 }
141
142 tls_requested = 1;
143 }
144 mu_iterator_destroy (&itr);
83 145
84 #endif /* WITH_TLS */ 146 if (tls_requested && !tls_ok)
147 {
148 mu_error (_("TLS is not configured, but requested in the "
149 "configuration"));
150 errors = 1;
151 }
152
153 if (errors)
154 return 1;
155
156 return 0;
157 }
85 158
86 /* EOF */ 159 /* EOF */
......
...@@ -180,13 +180,16 @@ typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage, ...@@ -180,13 +180,16 @@ typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage,
180 180
181 struct mu_cfg_section 181 struct mu_cfg_section
182 { 182 {
183 const char *ident; 183 const char *ident; /* Section identifier */
184 char *label; 184 char *label; /* Label description */
185 mu_cfg_section_fp parser; 185 mu_cfg_section_fp parser; /* Parser function */
186 void *target; 186 void *data; /* Data pointer */
187 size_t offset; 187 size_t offset; /* Offset within target (see below) */
188 mu_list_t /* of mu_cfg_cont */ children; 188 mu_list_t /* of mu_cfg_cont */ children;
189 char *docstring; 189 char *docstring; /* Documentation string */
190 void *target; /* Actual pointer to the data. It is
191 recomputed each time the section is
192 reduced. */
190 }; 193 };
191 194
192 enum mu_cfg_cont_type 195 enum mu_cfg_cont_type
......
...@@ -28,7 +28,7 @@ typedef int (*mu_conn_loop_fp) (int fd, void *conn_data, void *server_data); ...@@ -28,7 +28,7 @@ typedef int (*mu_conn_loop_fp) (int fd, void *conn_data, void *server_data);
28 typedef void (*mu_conn_free_fp) (void *conn_data, void *server_data); 28 typedef void (*mu_conn_free_fp) (void *conn_data, void *server_data);
29 typedef int (*mu_server_idle_fp) (void *server_data); 29 typedef int (*mu_server_idle_fp) (void *server_data);
30 typedef void (*mu_server_free_fp) (void *server_data); 30 typedef void (*mu_server_free_fp) (void *server_data);
31 31
32 #define MU_SERVER_SUCCESS 0 32 #define MU_SERVER_SUCCESS 0
33 #define MU_SERVER_CLOSE_CONN 1 33 #define MU_SERVER_CLOSE_CONN 1
34 #define MU_SERVER_SHUTDOWN 2 34 #define MU_SERVER_SHUTDOWN 2
...@@ -40,7 +40,8 @@ int mu_server_set_idle (mu_server_t srv, mu_server_idle_fp fp); ...@@ -40,7 +40,8 @@ int mu_server_set_idle (mu_server_t srv, mu_server_idle_fp fp);
40 int mu_server_set_data (mu_server_t srv, void *data, mu_server_free_fp fp); 40 int mu_server_set_data (mu_server_t srv, void *data, mu_server_free_fp fp);
41 int mu_server_add_connection (mu_server_t srv, 41 int mu_server_add_connection (mu_server_t srv,
42 int fd, void *data, 42 int fd, void *data,
43 mu_conn_loop_fp loop, mu_conn_free_fp free); 43 mu_conn_loop_fp loop,
44 mu_conn_free_fp free);
44 struct timeval; 45 struct timeval;
45 int mu_server_set_timeout (mu_server_t srv, struct timeval *to); 46 int mu_server_set_timeout (mu_server_t srv, struct timeval *to);
46 int mu_server_count (mu_server_t srv, size_t *pcount); 47 int mu_server_count (mu_server_t srv, size_t *pcount);
...@@ -100,6 +101,7 @@ typedef struct mu_m_server_connect_data mu_m_server_connect_data_t; ...@@ -100,6 +101,7 @@ typedef struct mu_m_server_connect_data mu_m_server_connect_data_t;
100 typedef int (*mu_m_server_handler_fp) (int fd, struct sockaddr *sa, int salen, 101 typedef int (*mu_m_server_handler_fp) (int fd, struct sockaddr *sa, int salen,
101 struct mu_srv_config *pconf, 102 struct mu_srv_config *pconf,
102 void *data); 103 void *data);
104 typedef int (*mu_m_server_preflight_fp) (mu_m_server_t);
103 105
104 void mu_m_server_create (mu_m_server_t *psrv, const char *ident); 106 void mu_m_server_create (mu_m_server_t *psrv, const char *ident);
105 void mu_m_server_destroy (mu_m_server_t *pmsrv); 107 void mu_m_server_destroy (mu_m_server_t *pmsrv);
...@@ -109,6 +111,7 @@ void mu_m_server_get_type (mu_m_server_t srv, int *ptype); ...@@ -109,6 +111,7 @@ void mu_m_server_get_type (mu_m_server_t srv, int *ptype);
109 void mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_handler_fp f); 111 void mu_m_server_set_conn (mu_m_server_t srv, mu_m_server_handler_fp f);
110 void mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_handler_fp fun); 112 void mu_m_server_set_prefork (mu_m_server_t srv, mu_m_server_handler_fp fun);
111 void mu_m_server_set_data (mu_m_server_t srv, void *data); 113 void mu_m_server_set_data (mu_m_server_t srv, void *data);
114 void *mu_ip_server_get_data (mu_ip_server_t tcpsrv);
112 void mu_m_server_set_max_children (mu_m_server_t srv, size_t num); 115 void mu_m_server_set_max_children (mu_m_server_t srv, size_t num);
113 int mu_m_server_set_pidfile (mu_m_server_t srv, const char *pidfile); 116 int mu_m_server_set_pidfile (mu_m_server_t srv, const char *pidfile);
114 int mu_m_server_set_foreground (mu_m_server_t srv, int enable); 117 int mu_m_server_set_foreground (mu_m_server_t srv, int enable);
...@@ -119,6 +122,8 @@ void mu_m_server_set_sigset (mu_m_server_t srv, sigset_t *sigset); ...@@ -119,6 +122,8 @@ void mu_m_server_set_sigset (mu_m_server_t srv, sigset_t *sigset);
119 void mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int)); 122 void mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int));
120 void mu_m_server_set_app_data_size (mu_m_server_t srv, size_t size); 123 void mu_m_server_set_app_data_size (mu_m_server_t srv, size_t size);
121 int mu_m_server_set_config_size (mu_m_server_t srv, size_t size); 124 int mu_m_server_set_config_size (mu_m_server_t srv, size_t size);
125 void mu_m_server_set_preflight (mu_m_server_t srv,
126 mu_m_server_preflight_fp fun);
122 127
123 struct mu_srv_config *mu_m_server_listen (mu_m_server_t msrv, 128 struct mu_srv_config *mu_m_server_listen (mu_m_server_t msrv,
124 struct mu_sockaddr *s, int type); 129 struct mu_sockaddr *s, int type);
...@@ -144,5 +149,4 @@ int mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen); ...@@ -144,5 +149,4 @@ int mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen);
144 struct mu_cfg_param; 149 struct mu_cfg_param;
145 void mu_m_server_cfg_init (mu_m_server_t msrv, struct mu_cfg_param *app_param); 150 void mu_m_server_cfg_init (mu_m_server_t msrv, struct mu_cfg_param *app_param);
146 151
147
148 #endif 152 #endif
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
20 # include <mailutils/types.h> 20 # include <mailutils/types.h>
21 # include <mailutils/stream.h> 21 # include <mailutils/stream.h>
22 # include <mailutils/sys/stream.h> 22 # include <mailutils/sys/stream.h>
23 # include <mailutils/tls.h>
23 24
24 enum _mu_tls_stream_state 25 enum _mu_tls_stream_state
25 { 26 {
...@@ -40,9 +41,16 @@ struct _mu_tls_stream ...@@ -40,9 +41,16 @@ struct _mu_tls_stream
40 { 41 {
41 struct _mu_stream stream; 42 struct _mu_stream stream;
42 enum _mu_tls_stream_state state; 43 enum _mu_tls_stream_state state;
44 int session_type; /* Either GNUTLS_CLIENT or GNUTLS_SERVER */
43 gnutls_session_t session; 45 gnutls_session_t session;
44 int tls_err; 46 int tls_err;
45 mu_stream_t transport[2]; 47 mu_stream_t transport[2];
48 struct mu_tls_config conf;
49 gnutls_certificate_credentials_t cred;
46 }; 50 };
47 51
52 extern int mu_tls_io_stream_create (mu_stream_t *pstream,
53 mu_stream_t transport, int flags,
54 struct _mu_tls_stream *master);
55
48 #endif 56 #endif
......
...@@ -21,39 +21,67 @@ ...@@ -21,39 +21,67 @@
21 21
22 #include <mailutils/types.h> 22 #include <mailutils/types.h>
23 #include <mailutils/cli.h> 23 #include <mailutils/cli.h>
24 #include <mailutils/util.h>
24 25
25 #ifdef __cplusplus 26 #ifdef __cplusplus
26 extern "C" { 27 extern "C" {
27 #endif 28 #endif
28 29
29 struct mu_tls_module_config 30 struct mu_tls_config
30 { 31 {
31 int enable; 32 char *cert_file;
32 33 char *key_file;
33 char *ssl_cert; 34 char *ca_file;
34 int ssl_cert_safety_checks;
35
36 char *ssl_key;
37 int ssl_key_safety_checks;
38
39 char *ssl_cafile;
40 int ssl_cafile_safety_checks;
41
42 char *priorities; 35 char *priorities;
43 }; 36 };
44 37
45 extern int mu_tls_server_stream_create (mu_stream_t *stream, 38 enum mu_tls_type
46 mu_stream_t strin, mu_stream_t strout, 39 {
47 int flags); 40 MU_TLS_CLIENT,
48 extern int mu_tls_client_stream_create (mu_stream_t *stream, 41 MU_TLS_SERVER
49 mu_stream_t strin, mu_stream_t strout, 42 };
50 int flags);
51
52 extern int mu_check_tls_environment (void);
53 extern int mu_init_tls_libs (int x509);
54 extern void mu_deinit_tls_libs (void);
55 43
56 extern int mu_tls_enable; 44 extern int mu_tls_enable;
45 extern int mu_tls_cert_file_checks;
46 extern int mu_tls_key_file_checks;
47 extern int mu_tls_ca_file_checks;
48
49 #define MU_TLS_CERT_FILE_CHECKS \
50 (MU_FILE_SAFETY_GROUP_WRITABLE \
51 | MU_FILE_SAFETY_GROUP_WRITABLE \
52 | MU_FILE_SAFETY_LINKED_WRDIR)
53
54 #define MU_TLS_KEY_FILE_CHECKS \
55 (MU_FILE_SAFETY_ALL & ~MU_FILE_SAFETY_OWNER_MISMATCH)
56
57 #define MU_TLS_CA_FILE_CHECKS \
58 (MU_FILE_SAFETY_GROUP_WRITABLE \
59 | MU_FILE_SAFETY_GROUP_WRITABLE \
60 | MU_FILE_SAFETY_LINKED_WRDIR)
61
62 void mu_tls_cfg_init (void);
63
64 int mu_tls_stream_create (mu_stream_t *pstream,
65 mu_stream_t strin, mu_stream_t strout,
66 struct mu_tls_config const *conf,
67 enum mu_tls_type type,
68 int flags);
69 int mu_tls_client_stream_create (mu_stream_t *pstream,
70 mu_stream_t strin, mu_stream_t strout,
71 int flags);
72
73 void mu_deinit_tls_libs (void);
74 int mu_init_tls_libs (void);
75
76 enum mu_tls_config_status
77 {
78 MU_TLS_CONFIG_OK, /* Configuration OK */
79 MU_TLS_CONFIG_NULL, /* Configuration is empty */
80 MU_TLS_CONFIG_UNSAFE, /* At least one file is considered unsafe */
81 MU_TLS_CONFIG_FAIL /* Some files absent (or other system error) */
82 };
83
84 int mu_tls_config_check (struct mu_tls_config const *conf, int verbose);
57 85
58 extern struct mu_cli_capa mu_cli_capa_tls; 86 extern struct mu_cli_capa mu_cli_capa_tls;
59 87
......
...@@ -161,7 +161,7 @@ dup_container (struct mu_cfg_cont **pcont) ...@@ -161,7 +161,7 @@ dup_container (struct mu_cfg_cont **pcont)
161 newcont->v.section.ident = oldcont->v.section.ident; 161 newcont->v.section.ident = oldcont->v.section.ident;
162 newcont->v.section.label = oldcont->v.section.label; 162 newcont->v.section.label = oldcont->v.section.label;
163 newcont->v.section.parser = oldcont->v.section.parser; 163 newcont->v.section.parser = oldcont->v.section.parser;
164 newcont->v.section.target = oldcont->v.section.target; 164 newcont->v.section.data = oldcont->v.section.data;
165 newcont->v.section.offset = oldcont->v.section.offset; 165 newcont->v.section.offset = oldcont->v.section.offset;
166 newcont->v.section.docstring = oldcont->v.section.docstring; 166 newcont->v.section.docstring = oldcont->v.section.docstring;
167 newcont->v.section.children = NULL; 167 newcont->v.section.children = NULL;
...@@ -281,11 +281,27 @@ mu_cfg_section_add_params (struct mu_cfg_section *sect, ...@@ -281,11 +281,27 @@ mu_cfg_section_add_params (struct mu_cfg_section *sect,
281 switch (c->type) 281 switch (c->type)
282 { 282 {
283 case mu_cfg_cont_section: 283 case mu_cfg_cont_section:
284 c->v.section.offset += param->offset; 284 if (param->data)
285 {
286 c->v.section.data = param->data;
287 c->v.section.offset = param->offset;
288 }
289 else if (c->v.section.data)
290 /* Keep data & offset */;
291 else
292 c->v.section.offset += param->offset;
285 break; 293 break;
286 294
287 case mu_cfg_cont_param: 295 case mu_cfg_cont_param:
288 container->v.param.offset += param->offset; 296 if (param->data)
297 {
298 container->v.param.data = param->data;
299 container->v.param.offset = param->offset;
300 }
301 else if (container->v.param.data)
302 /* Keep data & offset */;
303 else
304 container->v.param.offset += param->offset;
289 break; 305 break;
290 } 306 }
291 mu_cfg_section_add_container (sect, c); 307 mu_cfg_section_add_container (sect, c);
...@@ -298,7 +314,7 @@ mu_cfg_section_add_params (struct mu_cfg_section *sect, ...@@ -298,7 +314,7 @@ mu_cfg_section_add_params (struct mu_cfg_section *sect,
298 mu_config_clone_container (container); 314 mu_config_clone_container (container);
299 if (mu_refcount_value (container->refcount) > 1) 315 if (mu_refcount_value (container->refcount) > 1)
300 dup_container (&container); 316 dup_container (&container);
301 container->v.section.target = param->data; 317 container->v.section.data = param->data;
302 container->v.section.offset = param->offset; 318 container->v.section.offset = param->offset;
303 } 319 }
304 } 320 }
......
...@@ -972,10 +972,14 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data) ...@@ -972,10 +972,14 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
972 } 972 }
973 if (!sec->children) 973 if (!sec->children)
974 return MU_CFG_ITER_SKIP; 974 return MU_CFG_ITER_SKIP;
975 if (sdata->list->sec->target) 975 if (sec->data)
976 sec->target = sec->data;
977 else if (sdata->list->sec->target)
976 sec->target = (char*)sdata->list->sec->target + sec->offset; 978 sec->target = (char*)sdata->list->sec->target + sec->offset;
977 else if (sdata->target) 979 else if (sdata->target)
978 sec->target = (char*)sdata->target + sec->offset; 980 sec->target = (char*)sdata->target + sec->offset;
981 else
982 sec->target = NULL;
979 if (sec->parser) 983 if (sec->parser)
980 { 984 {
981 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, 985 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
......
...@@ -41,3 +41,4 @@ wicket ...@@ -41,3 +41,4 @@ wicket
41 assoc 41 assoc
42 acl 42 acl
43 server 43 server
44 tls
......
...@@ -216,6 +216,12 @@ mu_ip_server_set_data (mu_ip_server_t srv, ...@@ -216,6 +216,12 @@ mu_ip_server_set_data (mu_ip_server_t srv,
216 return 0; 216 return 0;
217 } 217 }
218 218
219 void *
220 mu_ip_server_get_data (mu_ip_server_t tcpsrv)
221 {
222 return tcpsrv->data;
223 }
224
219 int 225 int
220 mu_address_family_to_domain (int family) 226 mu_address_family_to_domain (int family)
221 { 227 {
......
...@@ -77,7 +77,7 @@ struct _mu_m_server ...@@ -77,7 +77,7 @@ struct _mu_m_server
77 mu_list_t srvlist; /* A list of configured mu_ip_server_t 77 mu_list_t srvlist; /* A list of configured mu_ip_server_t
78 objects. It is cleared after the objects 78 objects. It is cleared after the objects
79 are opened and attached to the server. */ 79 are opened and attached to the server. */
80 80 mu_m_server_preflight_fp preflight; /* Pre-flight check function */
81 mu_m_server_handler_fp conn; /* Connection handler function. */ 81 mu_m_server_handler_fp conn; /* Connection handler function. */
82 mu_m_server_handler_fp prefork;/* Pre-fork function. */ 82 mu_m_server_handler_fp prefork;/* Pre-fork function. */
83 void *data; /* User-supplied data for conn and prefork. */ 83 void *data; /* User-supplied data for conn and prefork. */
...@@ -366,6 +366,12 @@ mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int)) ...@@ -366,6 +366,12 @@ mu_m_server_set_strexit (mu_m_server_t srv, const char *(*fun) (int))
366 srv->strexit = fun; 366 srv->strexit = fun;
367 } 367 }
368 368
369 void
370 mu_m_server_set_preflight (mu_m_server_t srv, mu_m_server_preflight_fp fun)
371 {
372 srv->preflight = fun;
373 }
374
369 int 375 int
370 mu_m_server_get_srvlist (mu_m_server_t srv, mu_list_t *plist) 376 mu_m_server_get_srvlist (mu_m_server_t srv, mu_list_t *plist)
371 { 377 {
...@@ -565,6 +571,7 @@ mu_m_server_destroy (mu_m_server_t *pmsrv) ...@@ -565,6 +571,7 @@ mu_m_server_destroy (mu_m_server_t *pmsrv)
565 { 571 {
566 mu_m_server_t msrv = *pmsrv; 572 mu_m_server_t msrv = *pmsrv;
567 mu_list_remove (m_server_list, msrv); 573 mu_list_remove (m_server_list, msrv);
574 mu_list_destroy (&msrv->srvlist);
568 mu_server_destroy (&msrv->server); 575 mu_server_destroy (&msrv->server);
569 free (msrv->child_pid); 576 free (msrv->child_pid);
570 /* FIXME: Send processes the TERM signal here?*/ 577 /* FIXME: Send processes the TERM signal here?*/
...@@ -594,17 +601,16 @@ tcp_conn_free (void *conn_data, void *server_data) ...@@ -594,17 +601,16 @@ tcp_conn_free (void *conn_data, void *server_data)
594 } 601 }
595 602
596 static int 603 static int
597 _open_conn (void *item, void *data) 604 open_connection (mu_ip_server_t tcpsrv, mu_m_server_t msrv)
598 { 605 {
599 mu_ip_server_t tcpsrv = item;
600 mu_m_server_t msrv = data;
601 int rc = mu_ip_server_open (tcpsrv); 606 int rc = mu_ip_server_open (tcpsrv);
602 if (rc) 607 if (rc)
603 { 608 {
604 mu_error (_("cannot open connection on %s: %s"), 609 mu_error (_("cannot open connection on %s: %s"),
605 mu_ip_server_addrstr (tcpsrv), mu_strerror (rc)); 610 mu_ip_server_addrstr (tcpsrv), mu_strerror (rc));
606 return 0; 611 return rc;
607 } 612 }
613
608 rc = mu_server_add_connection (msrv->server, 614 rc = mu_server_add_connection (msrv->server,
609 mu_ip_server_get_fd (tcpsrv), 615 mu_ip_server_get_fd (tcpsrv),
610 tcpsrv, 616 tcpsrv,
...@@ -614,9 +620,8 @@ _open_conn (void *item, void *data) ...@@ -614,9 +620,8 @@ _open_conn (void *item, void *data)
614 mu_error (_("cannot add connection %s: %s"), 620 mu_error (_("cannot add connection %s: %s"),
615 mu_ip_server_addrstr (tcpsrv), mu_strerror (rc)); 621 mu_ip_server_addrstr (tcpsrv), mu_strerror (rc));
616 mu_ip_server_shutdown (tcpsrv); 622 mu_ip_server_shutdown (tcpsrv);
617 mu_ip_server_destroy (&tcpsrv);
618 } 623 }
619 return 0; 624 return rc;
620 } 625 }
621 626
622 int 627 int
...@@ -624,16 +629,36 @@ mu_m_server_run (mu_m_server_t msrv) ...@@ -624,16 +629,36 @@ mu_m_server_run (mu_m_server_t msrv)
624 { 629 {
625 int rc; 630 int rc;
626 size_t count; 631 size_t count;
627 mode_t saved_umask = umask (0117); 632 mode_t saved_umask;
628 mu_list_foreach (msrv->srvlist, _open_conn, msrv); 633 mu_iterator_t itr;
634
635 saved_umask = umask (0117);
636 mu_list_get_iterator (msrv->srvlist, &itr);
637 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
638 {
639 mu_ip_server_t tcpsrv;
640 mu_iterator_current (itr, (void**) &tcpsrv);
641 if (open_connection (tcpsrv, msrv))
642 {
643 mu_iterator_ctl (itr, mu_itrctl_delete_nd, NULL);
644 mu_ip_server_destroy (&tcpsrv);
645 }
646 }
629 umask (saved_umask); 647 umask (saved_umask);
630 mu_list_destroy (&msrv->srvlist); 648 mu_iterator_destroy (&itr);
649
631 MU_ASSERT (mu_server_count (msrv->server, &count)); 650 MU_ASSERT (mu_server_count (msrv->server, &count));
632 if (count == 0) 651 if (count == 0)
633 { 652 {
634 mu_error (_("no servers configured: exiting")); 653 mu_error (_("no servers configured: exiting"));
635 exit (1); 654 exit (1);
636 } 655 }
656 if (msrv->preflight && msrv->preflight (msrv))
657 {
658 mu_error (_("%s: preflight check failed"), msrv->ident);
659 return MU_ERR_FAILURE;
660 }
661
637 if (msrv->ident) 662 if (msrv->ident)
638 mu_diag_output (MU_DIAG_INFO, _("%s started"), msrv->ident); 663 mu_diag_output (MU_DIAG_INFO, _("%s started"), msrv->ident);
639 rc = mu_server_run (msrv->server); 664 rc = mu_server_run (msrv->server);
...@@ -642,8 +667,6 @@ mu_m_server_run (mu_m_server_t msrv) ...@@ -642,8 +667,6 @@ mu_m_server_run (mu_m_server_t msrv)
642 mu_diag_output (MU_DIAG_INFO, _("%s terminated"), msrv->ident); 667 mu_diag_output (MU_DIAG_INFO, _("%s terminated"), msrv->ident);
643 return rc; 668 return rc;
644 } 669 }
645
646
647 670
648 int 671 int
649 mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen) 672 mu_m_server_check_acl (mu_m_server_t msrv, struct sockaddr *s, int salen)
......
...@@ -29,9 +29,18 @@ libmu_auth_la_SOURCES = \ ...@@ -29,9 +29,18 @@ libmu_auth_la_SOURCES = \
29 radius.c\ 29 radius.c\
30 sql.c\ 30 sql.c\
31 sql.h\ 31 sql.h\
32 tls.c\
33 virtual.c 32 virtual.c
34 33
34 libmu_auth_la_SOURCES += tlsconf.c tlsvar.c
35
36 if MU_COND_GNUTLS
37 libmu_auth_la_SOURCES += \
38 tls.c\
39 tlsiostr.c
40 else
41 libmu_auth_la_SOURCES += notls.c
42 endif
43
35 libmu_auth_la_LIBADD = ${MU_LIB_MAILUTILS} @MU_AUTHLIBS@ @SQLLIB@ @LTLIBINTL@ 44 libmu_auth_la_LIBADD = ${MU_LIB_MAILUTILS} @MU_AUTHLIBS@ @SQLLIB@ @LTLIBINTL@
36 libmu_auth_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ 45 libmu_auth_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
37 libmu_auth_la_DEPENDENCIES = @SQLLIB_DEPENDENCY@ 46 libmu_auth_la_DEPENDENCIES = @SQLLIB_DEPENDENCY@
......
1 /* Declare fail-only TLS interfaces in the absense of GNU TLS */
2 #if HAVE_CONFIG_H
3 # include <config.h>
4 #endif
5 #include <mailutils/tls.h>
6 #include <mailutils/errno.h>
7
8 int
9 mu_tls_stream_create (mu_stream_t *pstream,
10 mu_stream_t strin, mu_stream_t strout,
11 struct mu_tls_config const *conf,
12 enum mu_tls_type type,
13 int flags)
14 {
15 return ENOSYS;
16 }
17
18 void
19 mu_deinit_tls_libs (void)
20 {
21 }
22
23 int
24 mu_init_tls_libs (void)
25 {
26 mu_tls_enable = 0;
27 return 0;
28 }
29
...@@ -20,123 +20,33 @@ ...@@ -20,123 +20,33 @@
20 # include <config.h> 20 # include <config.h>
21 #endif 21 #endif
22 22
23 #include <stdio.h>
24 #include <stdlib.h> 23 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <string.h>
29 24
30 #include <mailutils/error.h>
31 #include <mailutils/mu_auth.h>
32 #include <mailutils/tls.h> 25 #include <mailutils/tls.h>
33 #include <mailutils/nls.h> 26 #include <mailutils/nls.h>
34 #include <mailutils/stream.h> 27 #include <mailutils/stream.h>
28 #include <mailutils/error.h>
35 #include <mailutils/errno.h> 29 #include <mailutils/errno.h>
36 #include <mailutils/util.h>
37 #include <mailutils/property.h> 30 #include <mailutils/property.h>
38 #include <mailutils/cli.h> 31 #include <mailutils/mu_auth.h>
39
40 #define SSL_CERT_FILE_CHECKS (MU_FILE_SAFETY_GROUP_WRITABLE | \
41 MU_FILE_SAFETY_GROUP_WRITABLE | \
42 MU_FILE_SAFETY_LINKED_WRDIR)
43
44 #define SSL_KEY_FILE_CHECKS (MU_FILE_SAFETY_ALL & \
45 ~MU_FILE_SAFETY_OWNER_MISMATCH)
46
47 #define SSL_CA_FILE_CHECKS (MU_FILE_SAFETY_GROUP_WRITABLE | \
48 MU_FILE_SAFETY_GROUP_WRITABLE | \
49 MU_FILE_SAFETY_LINKED_WRDIR)
50
51 struct mu_tls_module_config mu_tls_module_config = {
52 #ifdef WITH_TLS
53 1, /* enable by default */
54
55 NULL, /* Certificate file */
56 SSL_CERT_FILE_CHECKS,
57
58 NULL, /* Key file */
59 SSL_KEY_FILE_CHECKS, /* Stringent safety checks for keys */
60
61 NULL, /* CA file */
62 SSL_CA_FILE_CHECKS
63 #else
64 0
65 #endif
66 };
67
68 #ifdef WITH_TLS
69 32
70 #include <gnutls/gnutls.h> 33 #include <gnutls/gnutls.h>
71 #include <mailutils/sys/tls-stream.h> 34 #include <mailutils/sys/tls-stream.h>
72 35
73 static gnutls_certificate_server_credentials x509_cred; 36 static void
74
75 /* Return: zero means NOT READY, one means READY */
76 int
77 mu_check_tls_environment (void)
78 {
79 if (!mu_tls_module_config.enable)
80 return 0;
81 if (mu_tls_module_config.ssl_cert && mu_tls_module_config.ssl_key)
82 {
83 int rc = mu_file_safety_check (mu_tls_module_config.ssl_cert,
84 mu_tls_module_config.ssl_cert_safety_checks,
85 -1, NULL);
86 if (rc)
87 {
88 mu_error ("%s: %s", mu_tls_module_config.ssl_cert,
89 mu_strerror (rc));
90 return 0;
91 }
92 rc = mu_file_safety_check (mu_tls_module_config.ssl_key,
93 mu_tls_module_config.ssl_key_safety_checks,
94 -1, NULL);
95 if (rc)
96 {
97 mu_error ("%s: %s", mu_tls_module_config.ssl_key,
98 mu_strerror (rc));
99 return 0;
100 }
101
102 if (mu_tls_module_config.ssl_cafile)
103 {
104 rc = mu_file_safety_check (mu_tls_module_config.ssl_cafile,
105 mu_tls_module_config.ssl_cafile_safety_checks,
106 -1, NULL);
107 if (rc)
108 {
109 mu_error ("%s: %s", mu_tls_module_config.ssl_cafile,
110 mu_strerror (rc));
111 return 0;
112 }
113 }
114 }
115 else
116 return 0;
117
118 return 1;
119 }
120
121 int mu_tls_enable = 0;
122
123 #ifdef DEBUG_TLS
124 void
125 _mu_gtls_logger(int level, const char *text) 37 _mu_gtls_logger(int level, const char *text)
126 { 38 {
127 mu_diag_output (MU_DIAG_DEBUG, "GnuTLS(%d): %s", level, text); 39 int len = strlen (text);
40 if (text[len-1] == '\n')
41 len--;
42 mu_diag_output (MU_DIAG_DEBUG, "GnuTLS(%d): %.*s", level, len, text);
128 } 43 }
129 #endif
130 44
131 void 45 void
132 mu_deinit_tls_libs (void) 46 mu_deinit_tls_libs (void)
133 { 47 {
134 if (mu_tls_enable) 48 if (mu_tls_enable)
135 { 49 gnutls_global_deinit ();
136 if (x509_cred)
137 gnutls_certificate_free_credentials (x509_cred);
138 gnutls_global_deinit ();
139 }
140 mu_tls_enable = 0; 50 mu_tls_enable = 0;
141 } 51 }
142 52
...@@ -147,270 +57,31 @@ _onexit_deinit (void *ptr MU_ARG_UNUSED) ...@@ -147,270 +57,31 @@ _onexit_deinit (void *ptr MU_ARG_UNUSED)
147 } 57 }
148 58
149 int 59 int
150 mu_init_tls_libs (int x509_setup) 60 mu_init_tls_libs (void)
151 { 61 {
152 if (!mu_tls_enable) 62 if (!mu_tls_enable)
153 { 63 {
154 int rc; 64 int rc = gnutls_global_init ();
155 if ((rc = gnutls_global_init ()) == GNUTLS_E_SUCCESS) 65 if (rc == GNUTLS_E_SUCCESS)
156 mu_tls_enable = 1;
157 else
158 {
159 mu_error ("gnutls_global_init: %s", gnutls_strerror (rc));
160 return 0;
161 }
162 mu_onexit (_onexit_deinit, NULL);
163 }
164
165 if (x509_setup && !x509_cred)
166 {
167 gnutls_certificate_allocate_credentials (&x509_cred);
168 if (mu_tls_module_config.ssl_cafile)
169 gnutls_certificate_set_x509_trust_file (x509_cred,
170 mu_tls_module_config.ssl_cafile,
171 GNUTLS_X509_FMT_PEM);
172
173 gnutls_certificate_set_x509_key_file (x509_cred,
174 mu_tls_module_config.ssl_cert,
175 mu_tls_module_config.ssl_key,
176 GNUTLS_X509_FMT_PEM);
177 }
178
179 #ifdef DEBUG_TLS
180 gnutls_global_set_log_function (_mu_gtls_logger);
181 gnutls_global_set_log_level (110);
182 #endif
183 return mu_tls_enable;
184 }
185
186 static char default_priority_string[] = "NORMAL";
187
188 static gnutls_session_t
189 initialize_tls_session (void)
190 {
191 gnutls_session_t session = 0;
192
193 gnutls_init (&session, GNUTLS_SERVER);
194 gnutls_priority_set_direct (session,
195 mu_tls_module_config.priorities
196 ? mu_tls_module_config.priorities
197 : default_priority_string,
198 NULL);
199 gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
200 gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
201
202 return session;
203 }
204
205
206 /* ************************* TLS Stream Support **************************** */
207
208 static int
209 _tls_io_close (mu_stream_t stream)
210 {
211 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
212
213 return mu_stream_close (sp->transport);
214 }
215
216 static void
217 _tls_io_done (struct _mu_stream *stream)
218 {
219 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
220 mu_stream_unref (sp->transport);
221 }
222
223 static int
224 _tls_io_flush (struct _mu_stream *stream)
225 {
226 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
227 return mu_stream_flush (sp->transport);
228 }
229
230 static int
231 _tls_io_read (struct _mu_stream *stream, char *buf, size_t bufsize,
232 size_t *pnread)
233 {
234 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
235 int rc;
236
237 if (sp->up->state != state_open)
238 return EINVAL;
239 rc = gnutls_record_recv (sp->up->session, buf, bufsize);
240 if (rc >= 0)
241 {
242 *pnread = rc;
243 return 0;
244 }
245 sp->up->tls_err = rc;
246 return EIO;
247 }
248
249 static int
250 _tls_io_write (struct _mu_stream *stream, const char *buf, size_t bufsize,
251 size_t *pnwrite)
252 {
253 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
254 int rc;
255
256 if (sp->up->state != state_open)
257 return EINVAL;
258
259 /* gnutls_record_send() docs say:
260 If the EINTR is returned by the internal push function (write())
261 then GNUTLS_E_INTERRUPTED, will be returned. If GNUTLS_E_INTERRUPTED or
262 GNUTLS_E_AGAIN is returned you must call this function again, with the
263 same parameters. Otherwise the write operation will be
264 corrupted and the connection will be terminated. */
265
266 do
267 rc = gnutls_record_send (sp->up->session, buf, bufsize);
268 while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
269
270 if (rc < 0)
271 {
272 sp->up->tls_err = rc;
273 return EIO;
274 }
275
276 *pnwrite = rc;
277
278 return 0;
279 }
280
281 static int
282 _tls_rd_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
283 {
284 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
285 int rc = EINVAL;
286
287 if (*pflags == MU_STREAM_READY_RD)
288 rc = mu_stream_wait (sp->transport, pflags, tvp);
289 return rc;
290 }
291
292 static int
293 _tls_wr_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
294 {
295 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
296 int rc = EINVAL;
297
298 if (*pflags == MU_STREAM_READY_WR)
299 rc = mu_stream_wait (sp->transport, pflags, tvp);
300 return rc;
301 }
302
303 static int
304 get_cipher_info (gnutls_session_t session, mu_property_t *pprop)
305 {
306 mu_property_t prop;
307 const char *s;
308 int rc;
309
310 if (!pprop)
311 return EINVAL;
312
313 rc = mu_property_create_init (&prop, mu_assoc_property_init, NULL);
314 if (rc)
315 return rc;
316
317 s = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
318 mu_property_set_value (prop, "protocol", s, 1);
319
320 s = gnutls_cipher_get_name (gnutls_cipher_get (session));
321 mu_property_set_value (prop, "cipher", s, 1);
322
323 s = gnutls_mac_get_name (gnutls_mac_get (session));
324 mu_property_set_value (prop, "mac", s, 1);
325
326 *pprop = prop;
327
328 return 0;
329 }
330
331 static int
332 _tls_io_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg)
333 {
334 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
335
336 switch (code)
337 {
338 case MU_IOCTL_TRANSPORT:
339 if (!arg)
340 return EINVAL;
341 else
342 { 66 {
343 mu_transport_t *ptrans = arg; 67 mu_tls_enable = 1;
344 switch (opcode) 68 mu_onexit (_onexit_deinit, NULL);
69 if (mu_debug_level_p (MU_DEBCAT_TLS, MU_DEBUG_PROT))
345 { 70 {
346 case MU_IOCTL_OP_GET: 71 gnutls_global_set_log_function (_mu_gtls_logger);
347 ptrans[0] = (mu_transport_t) sp->transport; 72 gnutls_global_set_log_level (110);
348 ptrans[1] = NULL;
349 break;
350
351 case MU_IOCTL_OP_SET:
352 return ENOSYS;
353
354 default:
355 return EINVAL;
356 } 73 }
357 } 74 }
358 break; 75 else
359
360 case MU_IOCTL_TLSSTREAM:
361 switch (opcode)
362 { 76 {
363 case MU_IOCTL_TLS_GET_CIPHER_INFO: 77 mu_error ("gnutls_global_init: %s", gnutls_strerror (rc));
364 return get_cipher_info (sp->up->session, arg);
365
366 default:
367 return EINVAL;
368 } 78 }
369 break;
370
371 default:
372 return ENOSYS;
373 } 79 }
374 return 0; 80 return mu_tls_enable;
375 }
376
377 static int
378 _mu_tls_io_stream_create (mu_stream_t *pstream,
379 mu_stream_t transport, int flags,
380 struct _mu_tls_stream *master)
381 {
382 struct _mu_tls_io_stream *sp;
383
384 sp = (struct _mu_tls_io_stream *)
385 _mu_stream_create (sizeof (*sp), (flags & MU_STREAM_RDWR) | _MU_STR_OPEN);
386 if (!sp)
387 return ENOMEM;
388
389 if (flags & MU_STREAM_READ)
390 {
391 sp->stream.read = _tls_io_read;
392 sp->stream.wait = _tls_rd_wait;
393 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_full, 0);
394 }
395 else
396 {
397 sp->stream.write = _tls_io_write;
398 sp->stream.wait = _tls_wr_wait;
399 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 0);
400 }
401 sp->stream.flush = _tls_io_flush;
402 sp->stream.close = _tls_io_close;
403 sp->stream.done = _tls_io_done;
404 sp->stream.ctl = _tls_io_ioctl;
405
406 mu_stream_ref (transport);
407 sp->transport = transport;
408 sp->up = master;
409 *pstream = (mu_stream_t) sp;
410 return 0;
411 } 81 }
412
413 82
83 /* TLS push & pull functions */
84
414 static ssize_t 85 static ssize_t
415 _tls_stream_pull (gnutls_transport_ptr_t fd, void *buf, size_t size) 86 _tls_stream_pull (gnutls_transport_ptr_t fd, void *buf, size_t size)
416 { 87 {
...@@ -443,82 +114,125 @@ _tls_stream_push (gnutls_transport_ptr_t fd, const void *buf, size_t size) ...@@ -443,82 +114,125 @@ _tls_stream_push (gnutls_transport_ptr_t fd, const void *buf, size_t size)
443 mu_stream_flush (stream); 114 mu_stream_flush (stream);
444 return size; 115 return size;
445 } 116 }
446
447 117
448 static int 118 static char default_priority_string[] = "NORMAL";
449 _tls_server_open (mu_stream_t stream)
450 {
451 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
452 int rc = 0;
453 mu_transport_t transport[2];
454
455 if (!mu_tls_module_config.enable)
456 return MU_ERR_DISABLED;
457 if (!stream || sp->state != state_init)
458 return EINVAL;
459
460 if (!mu_init_tls_libs (1))
461 return MU_ERR_FAILURE;
462
463 sp->session = initialize_tls_session ();
464 mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport);
465 gnutls_transport_set_ptr2 (sp->session,
466 (gnutls_transport_ptr_t) transport[0],
467 (gnutls_transport_ptr_t) transport[1]);
468 gnutls_transport_set_pull_function (sp->session, _tls_stream_pull);
469 gnutls_transport_set_push_function (sp->session, _tls_stream_push);
470
471 rc = gnutls_handshake (sp->session);
472 if (rc < 0)
473 {
474 gnutls_deinit (sp->session);
475 sp->tls_err = rc;
476 return EIO;
477 }
478 sp->state = state_open;
479 return 0;
480 }
481 119
482 static int 120 static int
483 prepare_client_session (mu_stream_t stream) 121 prep_session (mu_stream_t stream)
484 { 122 {
485 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream; 123 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
486 int rc; 124 gnutls_certificate_credentials_t cred = NULL;
487 mu_transport_t transport[2]; 125 mu_transport_t transport[2];
126 int rc;
127 const char *errp;
488 128
489 gnutls_init (&sp->session, GNUTLS_CLIENT); 129 if (!sp->cred)
490 gnutls_priority_set_direct (sp->session,
491 mu_tls_module_config.priorities
492 ? mu_tls_module_config.priorities
493 : default_priority_string,
494 NULL);
495 gnutls_certificate_allocate_credentials (&x509_cred);
496 if (mu_tls_module_config.ssl_cafile)
497 { 130 {
498 rc = gnutls_certificate_set_x509_trust_file (x509_cred, 131 rc = gnutls_certificate_allocate_credentials (&cred);
499 mu_tls_module_config.ssl_cafile, 132 if (rc)
500 GNUTLS_X509_FMT_PEM);
501 if (rc < 0)
502 { 133 {
134 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
135 ("gnutls_certificate_allocate_credentials: %s",
136 gnutls_strerror (rc)));
503 sp->tls_err = rc; 137 sp->tls_err = rc;
504 return -1; 138 return MU_ERR_FAILURE;
139 }
140
141 if (sp->conf.ca_file)
142 {
143 rc = gnutls_certificate_set_x509_trust_file (cred, sp->conf.ca_file,
144 GNUTLS_X509_FMT_PEM);
145 if (rc < 0)
146 {
147 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
148 ("can't use X509 CA file %s: %s",
149 sp->conf.ca_file,
150 gnutls_strerror (rc)));
151 goto cred_err;
152 }
153 }
154
155 if (sp->conf.cert_file && sp->conf.key_file)
156 {
157 rc = gnutls_certificate_set_x509_key_file (cred,
158 sp->conf.cert_file,
159 sp->conf.key_file,
160 GNUTLS_X509_FMT_PEM);
161 if (rc != GNUTLS_E_SUCCESS)
162 {
163 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
164 ("can't use X509 cert/key pair (%s,%s): %s",
165 sp->conf.cert_file,
166 sp->conf.key_file,
167 gnutls_strerror (rc)));
168 goto cred_err;
169 }
505 } 170 }
171 sp->cred = cred;
172 }
173
174 rc = gnutls_init (&sp->session, sp->session_type);
175 if (rc != GNUTLS_E_SUCCESS)
176 {
177 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
178 ("failed to initialize session: %s", gnutls_strerror (rc)));
179 goto cred_err;
506 } 180 }
507 181
508 gnutls_credentials_set (sp->session, GNUTLS_CRD_CERTIFICATE, x509_cred); 182 rc = gnutls_priority_set_direct (sp->session,
509 183 sp->conf.priorities
510 mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, transport); 184 ? sp->conf.priorities
185 : default_priority_string,
186 &errp);
187 if (rc != GNUTLS_E_SUCCESS)
188 {
189 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
190 ("error setting priorities near %s: %s",
191 errp, gnutls_strerror (rc)));
192 goto cred_err;
193 }
194
195 rc = gnutls_credentials_set (sp->session, GNUTLS_CRD_CERTIFICATE, sp->cred);
196 if (rc)
197 {
198 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
199 ("gnutls_credentials_set: %s", gnutls_strerror (rc)));
200 goto sess_err;
201 }
202
203 if (sp->session_type == GNUTLS_SERVER)
204 gnutls_certificate_server_set_request (sp->session, GNUTLS_CERT_REQUEST);
205
206 rc = mu_stream_ioctl (stream, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET,
207 transport);
208 if (rc)
209 {
210 mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_ioctl", NULL, rc);
211 abort (); /* should not happen */
212 }
213
511 gnutls_transport_set_ptr2 (sp->session, 214 gnutls_transport_set_ptr2 (sp->session,
512 (gnutls_transport_ptr_t) transport[0], 215 (gnutls_transport_ptr_t) transport[0],
513 (gnutls_transport_ptr_t) transport[1]); 216 (gnutls_transport_ptr_t) transport[1]);
514 gnutls_transport_set_pull_function (sp->session, _tls_stream_pull); 217 gnutls_transport_set_pull_function (sp->session, _tls_stream_pull);
515 gnutls_transport_set_push_function (sp->session, _tls_stream_push); 218 gnutls_transport_set_push_function (sp->session, _tls_stream_push);
516 219
517 return 0; 220 return 0;
221
222 sess_err:
223 gnutls_deinit (sp->session);
224 cred_err:
225 if (sp->cred)
226 {
227 gnutls_certificate_free_credentials (sp->cred);
228 sp->cred = NULL;
229 }
230 sp->tls_err = rc;
231 return MU_ERR_FAILURE;
518 } 232 }
519 233
520 static int 234 static int
521 _tls_client_open (mu_stream_t stream) 235 _tls_open (mu_stream_t stream)
522 { 236 {
523 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream; 237 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
524 int rc = 0; 238 int rc = 0;
...@@ -527,32 +241,38 @@ _tls_client_open (mu_stream_t stream) ...@@ -527,32 +241,38 @@ _tls_client_open (mu_stream_t stream)
527 { 241 {
528 case state_closed: 242 case state_closed:
529 if (sp->session) 243 if (sp->session)
530 gnutls_deinit (sp->session); 244 {
245 gnutls_deinit (sp->session);
246 sp->session = NULL;
247 }
531 /* FALLTHROUGH */ 248 /* FALLTHROUGH */
532 249
533 case state_init: 250 case state_init:
534 if (!mu_init_tls_libs (0)) 251 rc = prep_session (stream);
535 return MU_ERR_FAILURE; 252 if (rc)
536 prepare_client_session (stream); 253 break;
537 rc = gnutls_handshake (sp->session); 254 rc = gnutls_handshake (sp->session);
538 if (rc < 0) 255 if (rc != GNUTLS_E_SUCCESS)
539 { 256 {
257 mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR,
258 ("gnutls_handshake: %s", gnutls_strerror (rc)));
540 sp->tls_err = rc; 259 sp->tls_err = rc;
541 gnutls_deinit (sp->session); 260 gnutls_deinit (sp->session);
261 sp->session = NULL;
542 sp->state = state_init; 262 sp->state = state_init;
543 return MU_ERR_FAILURE;
544 } 263 }
264 else
265 /* FIXME: if (ssl_cafile) verify_certificate (s->session); */
266 sp->state = state_open;
545 break; 267 break;
546 268
547 default: 269 default:
548 return MU_ERR_FAILURE; 270 rc = MU_ERR_BADOP;
549 } 271 }
550 272 return rc;
551 /* FIXME: if (ssl_cafile) verify_certificate (s->session); */
552 sp->state = state_open;
553 return 0;
554 } 273 }
555 274
275 /* TLS stream */
556 static int 276 static int
557 _tls_read (struct _mu_stream *str, char *buf, size_t bufsize, 277 _tls_read (struct _mu_stream *str, char *buf, size_t bufsize,
558 size_t *pnread) 278 size_t *pnread)
...@@ -570,6 +290,34 @@ _tls_write (struct _mu_stream *str, const char *buf, size_t bufsize, ...@@ -570,6 +290,34 @@ _tls_write (struct _mu_stream *str, const char *buf, size_t bufsize,
570 } 290 }
571 291
572 static int 292 static int
293 get_cipher_info (gnutls_session_t session, mu_property_t *pprop)
294 {
295 mu_property_t prop;
296 const char *s;
297 int rc;
298
299 if (!pprop)
300 return EINVAL;
301
302 rc = mu_property_create_init (&prop, mu_assoc_property_init, NULL);
303 if (rc)
304 return rc;
305
306 s = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
307 mu_property_set_value (prop, "protocol", s, 1);
308
309 s = gnutls_cipher_get_name (gnutls_cipher_get (session));
310 mu_property_set_value (prop, "cipher", s, 1);
311
312 s = gnutls_mac_get_name (gnutls_mac_get (session));
313 mu_property_set_value (prop, "mac", s, 1);
314
315 *pprop = prop;
316
317 return 0;
318 }
319
320 static int
573 _tls_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg) 321 _tls_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg)
574 { 322 {
575 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream; 323 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
...@@ -684,17 +432,18 @@ _tls_close (mu_stream_t stream) ...@@ -684,17 +432,18 @@ _tls_close (mu_stream_t stream)
684 return 0; 432 return 0;
685 } 433 }
686 434
435 static void free_conf (struct mu_tls_config *conf);
436
687 static void 437 static void
688 _tls_done (struct _mu_stream *stream) 438 _tls_done (struct _mu_stream *stream)
689 { 439 {
690 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream; 440 struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
691 441
692 if (sp->session && sp->state == state_closed) 442 if (sp->session)
693 { 443 gnutls_deinit (sp->session);
694 gnutls_deinit (sp->session); 444 if (sp->cred)
695 sp->state = state_destroyed; 445 gnutls_certificate_free_credentials (sp->cred);
696 } 446 free_conf (&sp->conf);
697
698 mu_stream_destroy (&sp->transport[0]); 447 mu_stream_destroy (&sp->transport[0]);
699 mu_stream_destroy (&sp->transport[1]); 448 mu_stream_destroy (&sp->transport[1]);
700 } 449 }
...@@ -710,24 +459,121 @@ _tls_error_string (struct _mu_stream *stream, int rc) ...@@ -710,24 +459,121 @@ _tls_error_string (struct _mu_stream *stream, int rc)
710 return mu_strerror (rc); 459 return mu_strerror (rc);
711 } 460 }
712 461
462 static void
463 free_conf (struct mu_tls_config *conf)
464 {
465 free (conf->cert_file);
466 free (conf->key_file);
467 free (conf->ca_file);
468 }
469
713 static int 470 static int
714 _mu_tls_stream_create (mu_stream_t *pstream, 471 copy_conf (struct mu_tls_config *dst, struct mu_tls_config const *src)
715 int (*openfn) (mu_stream_t stream), 472 {
716 mu_stream_t strin, mu_stream_t strout, int flags) 473 if (src->cert_file)
474 {
475 dst->cert_file = strdup (src->cert_file);
476 if (!dst->cert_file)
477 return errno;
478 }
479 else
480 dst->cert_file = NULL;
481
482 if (src->key_file)
483 {
484 dst->key_file = strdup (src->key_file);
485 if (!dst->cert_file)
486 {
487 int rc = errno;
488 free (dst->cert_file);
489 return rc;
490 }
491 }
492 else
493 dst->key_file = NULL;
494
495 if (src->ca_file)
496 {
497 dst->ca_file = strdup (src->ca_file);
498 if (!dst->ca_file)
499 {
500 int rc = errno;
501 free (dst->cert_file);
502 free (dst->key_file);
503 return rc;
504 }
505 }
506 else
507 dst->ca_file = NULL;
508
509 return 0;
510 }
511
512 int
513 mu_tls_stream_create (mu_stream_t *pstream,
514 mu_stream_t strin, mu_stream_t strout,
515 struct mu_tls_config const *conf,
516 enum mu_tls_type type,
517 int flags)
717 { 518 {
718 struct _mu_tls_stream *sp; 519 struct _mu_tls_stream *sp;
719 int rc; 520 int rc;
720 mu_stream_t stream; 521 mu_stream_t stream;
522 int session_type;
523
524 if (!pstream)
525 return MU_ERR_OUT_PTR_NULL;
526 if (!conf || !strin || !strout)
527 return EINVAL;
528
529 if (!mu_init_tls_libs ())
530 return ENOSYS;
531
532 switch (mu_tls_config_check (conf, 1))
533 {
534 case MU_TLS_CONFIG_OK:
535 case MU_TLS_CONFIG_NULL:
536 break;
537 case MU_TLS_CONFIG_UNSAFE:
538 return EACCES;
539 case MU_TLS_CONFIG_FAIL:
540 return ENOENT;
541 }
542
543 switch (type)
544 {
545 case MU_TLS_CLIENT:
546 session_type = GNUTLS_CLIENT;
547 break;
548
549 case MU_TLS_SERVER:
550 session_type = GNUTLS_SERVER;
551 break;
552
553 default:
554 return EINVAL;
555 }
721 556
722 sp = (struct _mu_tls_stream *) 557 sp = (struct _mu_tls_stream *)
723 _mu_stream_create (sizeof (*sp), MU_STREAM_RDWR); 558 _mu_stream_create (sizeof (*sp), MU_STREAM_RDWR);
724 if (!sp) 559 if (!sp)
725 return ENOMEM; 560 return ENOMEM;
561 sp->session_type = session_type;
562 sp->state = state_init;
563 sp->session = NULL;
564 sp->cred = NULL;
726 565
566 rc = copy_conf (&sp->conf, conf);
567 if (rc)
568 {
569 free (sp);
570 return rc;
571 }
572
727 sp->stream.read = _tls_read; 573 sp->stream.read = _tls_read;
728 sp->stream.write = _tls_write; 574 sp->stream.write = _tls_write;
729 sp->stream.flush = _tls_flush; 575 sp->stream.flush = _tls_flush;
730 sp->stream.open = openfn; 576 sp->stream.open = _tls_open;
731 sp->stream.close = _tls_close; 577 sp->stream.close = _tls_close;
732 sp->stream.done = _tls_done; 578 sp->stream.done = _tls_done;
733 sp->stream.ctl = _tls_ioctl; 579 sp->stream.ctl = _tls_ioctl;
...@@ -736,134 +582,43 @@ _mu_tls_stream_create (mu_stream_t *pstream, ...@@ -736,134 +582,43 @@ _mu_tls_stream_create (mu_stream_t *pstream,
736 582
737 mu_stream_set_buffer (strin, mu_buffer_none, 0); 583 mu_stream_set_buffer (strin, mu_buffer_none, 0);
738 mu_stream_set_buffer (strout, mu_buffer_none, 0); 584 mu_stream_set_buffer (strout, mu_buffer_none, 0);
739 rc = _mu_tls_io_stream_create (&sp->transport[0], strin, MU_STREAM_READ, sp);
740 if (rc)
741 {
742 free (sp);
743 return rc;
744 }
745
746 rc = _mu_tls_io_stream_create (&sp->transport[1], strout, MU_STREAM_WRITE,
747 sp);
748 if (rc)
749 {
750 free (sp);
751 free (sp->transport[0]);
752 return rc;
753 }
754 585
755 stream = (mu_stream_t) sp; 586 stream = (mu_stream_t) sp;
587
588 rc = mu_tls_io_stream_create (&sp->transport[0], strin,
589 MU_STREAM_READ, sp);
590 if (rc)
591 goto err;
592
593 rc = mu_tls_io_stream_create (&sp->transport[1], strout,
594 MU_STREAM_WRITE, sp);
595 if (rc)
596 goto err;
597
756 mu_stream_set_buffer (stream, mu_buffer_line, 0); 598 mu_stream_set_buffer (stream, mu_buffer_line, 0);
757 rc = mu_stream_open (stream); 599 rc = mu_stream_open (stream);
758 if (rc) 600 if (rc)
759 mu_stream_destroy (&stream); 601 goto err;
760 else 602 *pstream = stream;
761 *pstream = stream; 603 return 0;
604
605 err:
606 mu_stream_destroy (&stream);
762 return rc; 607 return rc;
763 } 608 }
764 609
765 int
766 mu_tls_server_stream_create (mu_stream_t *pstream,
767 mu_stream_t strin, mu_stream_t strout, int flags)
768 {
769 return _mu_tls_stream_create (pstream,
770 _tls_server_open,
771 strin, strout, flags);
772 }
773
774 int 610 int
775 mu_tls_client_stream_create (mu_stream_t *pstream, 611 mu_tls_client_stream_create (mu_stream_t *pstream,
776 mu_stream_t strin, mu_stream_t strout, int flags) 612 mu_stream_t strin, mu_stream_t strout, int flags)
777 { 613 {
778 return _mu_tls_stream_create (pstream, 614 struct mu_tls_config conf = {
779 _tls_client_open, 615 .cert_file = NULL,
780 strin, strout, flags); 616 .key_file = NULL,
781 } 617 .ca_file = NULL,
782 618 .priorities = NULL
783 static int 619 };
784 cb2_safety_checks (const char *name, void *data)
785 {
786 int defval;
787
788 if (data == &mu_tls_module_config.ssl_key_safety_checks)
789 defval = SSL_KEY_FILE_CHECKS;
790 else if (data == &mu_tls_module_config.ssl_cert_safety_checks)
791 defval = SSL_CERT_FILE_CHECKS;
792 else if (data == &mu_tls_module_config.ssl_cafile_safety_checks)
793 defval = SSL_CA_FILE_CHECKS;
794 else
795 {
796 mu_error (_("INTERNAL ERROR at %s:%d: unknown default value?"),
797 __FILE__, __LINE__);
798 defval = MU_FILE_SAFETY_ALL;
799 }
800 if (mu_file_safety_compose (data, name, defval))
801 mu_error (_("unknown keyword: %s"), name);
802 return 0;
803 }
804 620
805 static int 621 return mu_tls_stream_create (pstream, strin, strout, &conf, MU_TLS_CLIENT,
806 cb_safety_checks (void *data, mu_config_value_t *arg) 622 flags);
807 {
808 return mu_cfg_string_value_cb (arg, cb2_safety_checks, data);
809 } 623 }
810 624
811 static struct mu_cfg_param mu_tls_param[] = {
812 { "enable", mu_c_bool, &mu_tls_module_config.enable, 0, NULL,
813 N_("Enable TLS encryption.") },
814 { "ssl-cert", mu_c_string, &mu_tls_module_config.ssl_cert, 0, NULL,
815 N_("Specify SSL certificate file."),
816 N_("file") },
817 { "ssl-key", mu_c_string, &mu_tls_module_config.ssl_key, 0, NULL,
818 N_("Specify SSL certificate key file."),
819 N_("file") },
820 { "ssl-cafile", mu_c_string, &mu_tls_module_config.ssl_cafile, 0, NULL,
821 N_("Specify trusted CAs file."),
822 N_("file") },
823 { "ssl-priorities", mu_c_string, &mu_tls_module_config.priorities, 0, NULL,
824 N_("Set the priorities to use on the ciphers, key exchange methods, "
825 "macs and compression methods."),
826 NULL },
827 { "key-file-safety-checks", mu_cfg_callback,
828 &mu_tls_module_config.ssl_key_safety_checks, 0,
829 cb_safety_checks,
830 N_("Configure safety checks for SSL key file. Argument is a list or "
831 "sequence of check names optionally prefixed with '+' to enable or "
832 "'-' to disable the corresponding check. Valid check names are:\n"
833 "\n"
834 " none disable all checks\n"
835 " all enable all checks\n"
836 " gwrfil forbid group writable files\n"
837 " awrfil forbid world writable files\n"
838 " grdfil forbid group readable files\n"
839 " ardfil forbid world writable files\n"
840 " linkwrdir forbid symbolic links in group or world writable directories\n"
841 " gwrdir forbid files in group writable directories\n"
842 " awrdir forbid files in world writable directories\n"),
843 N_("arg: list") },
844 { "cert-file-safety-checks", mu_cfg_callback,
845 &mu_tls_module_config.ssl_cert_safety_checks, 0,
846 cb_safety_checks,
847 N_("Configure safety checks for SSL certificate. See above for a description of <arg>."),
848 N_("arg: list") },
849 { "ca-file-safety-checks", mu_cfg_callback,
850 &mu_tls_module_config.ssl_cafile_safety_checks, 0,
851 cb_safety_checks,
852 N_("Configure safety checks for SSL certificate authority file. See above for a description of <arg>."),
853 N_("arg: list") },
854 { NULL }
855 };
856
857 struct mu_auth_module mu_auth_tls_module = {
858 .name = "tls",
859 .cfg = mu_tls_param
860 };
861
862 #else
863 struct mu_auth_module mu_auth_tls_module = {
864 .name = "tls"
865 };
866 #endif /* WITH_TLS */
867
868 /* EOF */
869
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003-2004, 2007-2012, 2014-2017 Free Software
3 Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <stdlib.h>
23 #include <mailutils/tls.h>
24 #include <mailutils/nls.h>
25 #include <mailutils/error.h>
26 #include <mailutils/errno.h>
27 #include <mailutils/mu_auth.h>
28
29
30 struct safety_check_closure
31 {
32 int defval;
33 int *data;
34 };
35
36 static int
37 cb_safety_checks (const char *name, void *data)
38 {
39 struct safety_check_closure *cp = data;
40
41 if (mu_file_safety_compose (cp->data, name, cp->defval))
42 mu_error (_("unknown keyword: %s"), name);
43 return 0;
44 }
45
46 static int
47 cb_cert_safety_checks (void *data, mu_config_value_t *arg)
48 {
49 struct safety_check_closure clos;
50 clos.defval = MU_TLS_CERT_FILE_CHECKS;
51 clos.data = data;
52 return mu_cfg_string_value_cb (arg, cb_safety_checks, &clos);
53 }
54
55 static int
56 cb_key_safety_checks (void *data, mu_config_value_t *arg)
57 {
58 struct safety_check_closure clos;
59 clos.defval = MU_TLS_KEY_FILE_CHECKS;
60 clos.data = data;
61 return mu_cfg_string_value_cb (arg, cb_safety_checks, &clos);
62 }
63
64 static int
65 cb_ca_safety_checks (void *data, mu_config_value_t *arg)
66 {
67 struct safety_check_closure clos;
68 clos.defval = MU_TLS_CA_FILE_CHECKS;
69 clos.data = data;
70 return mu_cfg_string_value_cb (arg, cb_safety_checks, &clos);
71 }
72
73 static struct mu_cfg_param mu_tls_global_param[] = {
74 { "key-file", mu_cfg_callback,
75 &mu_tls_key_file_checks, 0,
76 cb_key_safety_checks,
77 N_("Configure safety checks for SSL key file. Argument is a list or "
78 "sequence of check names optionally prefixed with '+' to enable or "
79 "'-' to disable the corresponding check. Valid check names are:\n"
80 "\n"
81 " none disable all checks\n"
82 " all enable all checks\n"
83 " gwrfil forbid group writable files\n"
84 " awrfil forbid world writable files\n"
85 " grdfil forbid group readable files\n"
86 " ardfil forbid world writable files\n"
87 " linkwrdir forbid symbolic links in group or world writable directories\n"
88 " gwrdir forbid files in group writable directories\n"
89 " awrdir forbid files in world writable directories\n"),
90 N_("arg: list") },
91 { "cert-file", mu_cfg_callback,
92 &mu_tls_cert_file_checks, 0,
93 cb_cert_safety_checks,
94 N_("Configure safety checks for SSL certificate. See above for a description of <arg>."),
95 N_("arg: list") },
96 { "ca-file", mu_cfg_callback,
97 &mu_tls_ca_file_checks, 0,
98 cb_ca_safety_checks,
99 N_("Configure safety checks for SSL certificate authority file. See above for a description of <arg>."),
100 N_("arg: list") },
101 { NULL }
102 };
103
104 static struct mu_cfg_param tls_canned_param[] = {
105 { "ssl-certificate-file", mu_c_string,
106 NULL, mu_offsetof(struct mu_tls_config, cert_file), NULL,
107 N_("Specify SSL certificate file."),
108 N_("file") },
109 { "ssl-key-file", mu_c_string,
110 NULL, mu_offsetof(struct mu_tls_config, key_file), NULL,
111 N_("Specify SSL certificate key file."),
112 N_("file") },
113 { "ssl-ca-file", mu_c_string,
114 NULL, mu_offsetof(struct mu_tls_config, ca_file), NULL,
115 N_("Specify trusted CAs file."),
116 N_("file") },
117 { "ssl-priorities", mu_c_string,
118 NULL, mu_offsetof(struct mu_tls_config, priorities), NULL,
119 N_("Set the priorities to use on the ciphers, key exchange methods, "
120 "macs and compression methods."),
121 NULL },
122 { NULL }
123 };
124
125 void
126 mu_tls_cfg_init (void)
127 {
128 struct mu_cfg_section *section;
129
130 if (mu_create_canned_section ("tls", &section))
131 abort ();
132 section->docstring = N_("Configure TLS");
133 section->label = NULL;
134 mu_cfg_section_add_params (section, tls_canned_param);
135 }
136
137 struct mu_auth_module mu_auth_tls_module = {
138 .name = "tls-file-checks",
139 .cfg = mu_tls_global_param,
140 };
1 /* TLS I/O streams */
2
3 #if HAVE_CONFIG_H
4 # include <config.h>
5 #endif
6 #include <stdlib.h>
7 #include <gnutls/gnutls.h>
8 #include <mailutils/stream.h>
9 #include <mailutils/errno.h>
10 #include <mailutils/property.h>
11 #include <mailutils/sys/tls-stream.h>
12
13 static int
14 _tls_io_close (mu_stream_t stream)
15 {
16 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
17
18 return mu_stream_close (sp->transport);
19 }
20
21 static void
22 _tls_io_done (struct _mu_stream *stream)
23 {
24 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
25 mu_stream_unref (sp->transport);
26 }
27
28 static int
29 _tls_io_flush (struct _mu_stream *stream)
30 {
31 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
32 return mu_stream_flush (sp->transport);
33 }
34
35 static int
36 _tls_io_read (struct _mu_stream *stream, char *buf, size_t bufsize,
37 size_t *pnread)
38 {
39 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
40 int rc;
41
42 if (sp->up->state != state_open)
43 return EINVAL;
44 rc = gnutls_record_recv (sp->up->session, buf, bufsize);
45 if (rc >= 0)
46 {
47 *pnread = rc;
48 return 0;
49 }
50 sp->up->tls_err = rc;
51 return EIO;
52 }
53
54 static int
55 _tls_io_write (struct _mu_stream *stream, const char *buf, size_t bufsize,
56 size_t *pnwrite)
57 {
58 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
59 int rc;
60
61 if (sp->up->state != state_open)
62 return EINVAL;
63
64 /* gnutls_record_send() docs say:
65 If the EINTR is returned by the internal push function (write())
66 then GNUTLS_E_INTERRUPTED, will be returned. If GNUTLS_E_INTERRUPTED or
67 GNUTLS_E_AGAIN is returned you must call this function again, with the
68 same parameters. Otherwise the write operation will be
69 corrupted and the connection will be terminated. */
70
71 do
72 rc = gnutls_record_send (sp->up->session, buf, bufsize);
73 while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
74
75 if (rc < 0)
76 {
77 sp->up->tls_err = rc;
78 return EIO;
79 }
80
81 *pnwrite = rc;
82
83 return 0;
84 }
85
86 static int
87 _tls_rd_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
88 {
89 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
90 int rc = EINVAL;
91
92 if (*pflags == MU_STREAM_READY_RD)
93 rc = mu_stream_wait (sp->transport, pflags, tvp);
94 return rc;
95 }
96
97 static int
98 _tls_wr_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
99 {
100 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
101 int rc = EINVAL;
102
103 if (*pflags == MU_STREAM_READY_WR)
104 rc = mu_stream_wait (sp->transport, pflags, tvp);
105 return rc;
106 }
107
108 static int
109 get_cipher_info (gnutls_session_t session, mu_property_t *pprop)
110 {
111 mu_property_t prop;
112 const char *s;
113 int rc;
114
115 if (!pprop)
116 return EINVAL;
117
118 rc = mu_property_create_init (&prop, mu_assoc_property_init, NULL);
119 if (rc)
120 return rc;
121
122 s = gnutls_protocol_get_name (gnutls_protocol_get_version (session));
123 mu_property_set_value (prop, "protocol", s, 1);
124
125 s = gnutls_cipher_get_name (gnutls_cipher_get (session));
126 mu_property_set_value (prop, "cipher", s, 1);
127
128 s = gnutls_mac_get_name (gnutls_mac_get (session));
129 mu_property_set_value (prop, "mac", s, 1);
130
131 *pprop = prop;
132
133 return 0;
134 }
135
136 static int
137 _tls_io_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg)
138 {
139 struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
140
141 switch (code)
142 {
143 case MU_IOCTL_TRANSPORT:
144 if (!arg)
145 return EINVAL;
146 else
147 {
148 mu_transport_t *ptrans = arg;
149 switch (opcode)
150 {
151 case MU_IOCTL_OP_GET:
152 ptrans[0] = (mu_transport_t) sp->transport;
153 ptrans[1] = NULL;
154 break;
155
156 case MU_IOCTL_OP_SET:
157 return ENOSYS;
158
159 default:
160 return EINVAL;
161 }
162 }
163 break;
164
165 case MU_IOCTL_TLSSTREAM:
166 switch (opcode)
167 {
168 case MU_IOCTL_TLS_GET_CIPHER_INFO:
169 return get_cipher_info (sp->up->session, arg);
170
171 default:
172 return EINVAL;
173 }
174 break;
175
176 default:
177 return ENOSYS;
178 }
179 return 0;
180 }
181
182 int
183 mu_tls_io_stream_create (mu_stream_t *pstream,
184 mu_stream_t transport, int flags,
185 struct _mu_tls_stream *master)
186 {
187 struct _mu_tls_io_stream *sp;
188
189 sp = (struct _mu_tls_io_stream *)
190 _mu_stream_create (sizeof (*sp), (flags & MU_STREAM_RDWR) | _MU_STR_OPEN);
191 if (!sp)
192 return ENOMEM;
193
194 if (flags & MU_STREAM_READ)
195 {
196 sp->stream.read = _tls_io_read;
197 sp->stream.wait = _tls_rd_wait;
198 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_full, 0);
199 }
200 else
201 {
202 sp->stream.write = _tls_io_write;
203 sp->stream.wait = _tls_wr_wait;
204 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 0);
205 }
206 sp->stream.flush = _tls_io_flush;
207 sp->stream.close = _tls_io_close;
208 sp->stream.done = _tls_io_done;
209 sp->stream.ctl = _tls_io_ioctl;
210
211 mu_stream_ref (transport);
212 sp->transport = transport;
213 sp->up = master;
214 *pstream = (mu_stream_t) sp;
215 return 0;
216 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003-2004, 2007-2012, 2014-2017 Free Software
3 Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <mailutils/tls.h>
24 #include <mailutils/errno.h>
25
26 int mu_tls_enable = 0;
27 int mu_tls_cert_file_checks = MU_TLS_CERT_FILE_CHECKS;
28 int mu_tls_key_file_checks = MU_TLS_KEY_FILE_CHECKS;
29 int mu_tls_ca_file_checks = MU_TLS_CA_FILE_CHECKS;
30
31 static int
32 check_err(int rc)
33 {
34 switch (rc)
35 {
36 case MU_ERR_PERM_OWNER_MISMATCH:
37 case MU_ERR_PERM_GROUP_WRITABLE:
38 case MU_ERR_PERM_WORLD_WRITABLE:
39 case MU_ERR_PERM_GROUP_READABLE:
40 case MU_ERR_PERM_WORLD_READABLE:
41 case MU_ERR_PERM_LINKED_WRDIR:
42 case MU_ERR_PERM_DIR_IWGRP:
43 case MU_ERR_PERM_DIR_IWOTH:
44 return MU_TLS_CONFIG_UNSAFE;
45 default:
46 return MU_TLS_CONFIG_FAIL;
47 }
48 }
49
50 int
51 mu_tls_config_check (struct mu_tls_config const *conf, int verbose)
52 {
53 int rc;
54 int res = MU_TLS_CONFIG_NULL;
55
56 if (conf->cert_file)
57 {
58 rc = mu_file_safety_check (conf->cert_file, mu_tls_cert_file_checks,
59 -1, NULL);
60 if (rc)
61 {
62 if (verbose)
63 mu_error ("%s: %s", conf->cert_file, mu_strerror (rc));
64 return check_err (rc);
65 }
66 res = MU_TLS_CONFIG_OK;
67 }
68
69 if (conf->key_file)
70 {
71 rc = mu_file_safety_check (conf->key_file, mu_tls_key_file_checks,
72 -1, NULL);
73 if (rc)
74 {
75 if (verbose)
76 mu_error ("%s: %s", conf->key_file, mu_strerror (rc));
77 return check_err (rc);
78 }
79 res = MU_TLS_CONFIG_OK;
80 }
81
82 if (conf->ca_file)
83 {
84 rc = mu_file_safety_check (conf->ca_file, mu_tls_ca_file_checks,
85 -1, NULL);
86 if (rc)
87 {
88 if (verbose)
89 mu_error ("%s: %s", conf->ca_file, mu_strerror (rc));
90 return check_err (rc);
91 }
92 res = MU_TLS_CONFIG_OK;
93 }
94
95 if (conf->priorities)
96 res = MU_TLS_CONFIG_OK;
97
98 return res;
99
100 }
101
...@@ -104,17 +104,20 @@ capa_implementation (const char *name, struct pop3d_session *session) ...@@ -104,17 +104,20 @@ capa_implementation (const char *name, struct pop3d_session *session)
104 pop3d_outf ("%s %s\n", name, PACKAGE_STRING); 104 pop3d_outf ("%s %s\n", name, PACKAGE_STRING);
105 } 105 }
106 106
107 #ifdef WITH_TLS
108 static void 107 static void
109 capa_stls (const char *name, struct pop3d_session *session) 108 capa_stls (const char *name, struct pop3d_session *session)
110 { 109 {
111 if ((session->tls == tls_ondemand || session->tls == tls_required) 110 switch (session->tls_mode)
112 && tls_available && tls_done == 0) 111 {
113 pop3d_outf ("%s\n", name); 112 case tls_ondemand:
113 case tls_required:
114 pop3d_outf ("%s\n", name);
115 break;
116
117 default:
118 break;
119 }
114 } 120 }
115 #else
116 # define capa_stls NULL
117 #endif /* WITH_TLS */
118 121
119 static void 122 static void
120 capa_user (const char *name, struct pop3d_session *session) 123 capa_user (const char *name, struct pop3d_session *session)
......
...@@ -16,13 +16,12 @@ ...@@ -16,13 +16,12 @@
16 16
17 #include "pop3d.h" 17 #include "pop3d.h"
18 18
19 struct mu_tls_config global_tls_conf;
20
19 static struct pop3d_command command_table[] = { 21 static struct pop3d_command command_table[] = {
20 #ifdef WITH_TLS
21 { "STLS", pop3d_stls }, 22 { "STLS", pop3d_stls },
22 # define COMMAND_TABLE_HEAD 1 23 #define COMMAND_TABLE_STLS 0
23 #else 24 #define COMMAND_TABLE_PLAIN 1
24 # define COMMAND_TABLE_HEAD 0
25 #endif
26 { "RETR", pop3d_retr }, 25 { "RETR", pop3d_retr },
27 { "DELE", pop3d_dele }, 26 { "DELE", pop3d_dele },
28 { "USER", pop3d_user }, 27 { "USER", pop3d_user },
...@@ -39,8 +38,7 @@ static struct pop3d_command command_table[] = { ...@@ -39,8 +38,7 @@ static struct pop3d_command command_table[] = {
39 { NULL } 38 { NULL }
40 }; 39 };
41 40
42 static struct pop3d_command *command_table_head = 41 static struct pop3d_command *command_table_head;
43 command_table + COMMAND_TABLE_HEAD;
44 42
45 pop3d_command_handler_t 43 pop3d_command_handler_t
46 pop3d_find_command (const char *name) 44 pop3d_find_command (const char *name)
...@@ -54,57 +52,130 @@ pop3d_find_command (const char *name) ...@@ -54,57 +52,130 @@ pop3d_find_command (const char *name)
54 return p->handler; 52 return p->handler;
55 } 53 }
56 54
57 #ifdef WITH_TLS 55 int
58 void 56 stls_preflight (mu_m_server_t msrv)
59 enable_stls ()
60 { 57 {
61 command_table_head = command_table; 58 mu_list_t srvlist;
62 } 59 mu_iterator_t itr;
63 #endif 60 int errors = 0;
61 int tls_ok = mu_init_tls_libs ();
62 int tls_requested = 0;
63 int global_conf_status = 0;
64 64
65 struct error_table 65 if (global_tls_conf.cert_file)
66 { 66 global_conf_status = mu_tls_config_check (&global_tls_conf, 1);
67 int code; 67 else
68 const char *text; 68 global_conf_status = MU_TLS_CONFIG_NULL;
69 }; 69
70 mu_m_server_get_srvlist (msrv, &srvlist);
71 mu_list_get_iterator (srvlist, &itr);
72 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr))
73 {
74 mu_ip_server_t ipsrv;
75 struct pop3d_srv_config *cfg;
76 mu_iterator_current (itr, (void**) &ipsrv);
77 cfg = mu_ip_server_get_data (ipsrv);
78 switch (cfg->tls_mode)
79 {
80 case tls_unspecified:
81 if (cfg->tls_conf.cert_file)
82 {
83 cfg->tls_mode = tls_ondemand;
84 break;
85 }
86 else
87 cfg->tls_mode = tls_no;
88 /* fall through */
89 case tls_no:
90 continue;
91
92 default:
93 break;
94 }
95
96 switch (mu_tls_config_check (&cfg->tls_conf, 1))
97 {
98 case MU_TLS_CONFIG_OK:
99 if (!cfg->tls_conf.cert_file)
100 {
101 mu_error (_("server %s: no certificate set"),
102 mu_ip_server_addrstr (ipsrv));
103 errors = 1;
104 }
105 break;
106
107 case MU_TLS_CONFIG_NULL:
108 if (global_conf_status != MU_TLS_CONFIG_NULL)
109 {
110 cfg->tls_conf = global_tls_conf;
111 }
112 else
113 {
114 mu_error (_("server %s: no certificate set"),
115 mu_ip_server_addrstr (ipsrv));
116 errors = 1;
117 }
118 break;
119
120 default:
121 mu_error (_("server %s: TLS configuration failed"),
122 mu_ip_server_addrstr (ipsrv));
123 errors = 1;
124 }
125
126 tls_requested = 1;
127 }
128 mu_iterator_destroy (&itr);
129
130 if (tls_requested && !tls_ok)
131 {
132 mu_error (_("TLS is not configured, but requested in the "
133 "configuration"));
134 errors = 1;
135 }
136
137 if (errors)
138 return 1;
139
140 if (tls_requested)
141 command_table_head = command_table + COMMAND_TABLE_STLS;
142 else
143 command_table_head = command_table + COMMAND_TABLE_PLAIN;
144
145 return 0;
146 }
70 147
71 static struct error_table error_table[] = { 148 static char *error_table[] = {
72 { ERR_WRONG_STATE, "Incorrect state" }, 149 [ERR_WRONG_STATE] = "Incorrect state",
73 { ERR_BAD_ARGS, "Invalid arguments" }, 150 [ERR_BAD_ARGS] = "Invalid arguments",
74 { ERR_BAD_LOGIN, "[AUTH] Bad login" }, 151 [ERR_BAD_LOGIN] = "[AUTH] Bad login",
75 { ERR_NO_MESG, "No such message" }, 152 [ERR_NO_MESG] = "No such message",
76 { ERR_MESG_DELE, "Message has been deleted" }, 153 [ERR_MESG_DELE] = "Message has been deleted",
77 { ERR_NOT_IMPL, "Not implemented" }, 154 [ERR_NOT_IMPL] = "Not implemented",
78 { ERR_BAD_CMD, "Invalid command" }, 155 [ERR_BAD_CMD] = "Invalid command",
79 { ERR_MBOX_LOCK, "[IN-USE] Mailbox in use" }, 156 [ERR_MBOX_LOCK] = "[IN-USE] Mailbox in use",
80 { ERR_TOO_LONG, "Argument too long" }, 157 [ERR_TOO_LONG] = "Argument too long",
81 { ERR_NO_MEM, "Out of memory, quitting" }, 158 [ERR_NO_MEM] = "Out of memory] =quitting",
82 { ERR_SIGNAL, "Quitting on signal" }, 159 [ERR_SIGNAL] = "Quitting on signal",
83 { ERR_FILE, "Some deleted messages not removed" }, 160 [ERR_FILE] = "Some deleted messages not removed",
84 { ERR_NO_IFILE, "No input stream" }, 161 [ERR_NO_IFILE] = "No input stream",
85 { ERR_NO_OFILE, "No output stream" }, 162 [ERR_NO_OFILE] = "No output stream",
86 { ERR_IO, "I/O error" }, 163 [ERR_IO] = "I/O error",
87 { ERR_PROTO, "Remote protocol error" }, 164 [ERR_PROTO] = "Remote protocol error",
88 { ERR_TIMEOUT, "Session timed out" }, 165 [ERR_TIMEOUT] = "Session timed out",
89 { ERR_UNKNOWN, "Unknown error" }, 166 [ERR_UNKNOWN] = "Unknown error",
90 { ERR_MBOX_SYNC, "Mailbox was updated by other process" }, 167 [ERR_MBOX_SYNC] = "Mailbox was updated by other process",
91 #ifdef WITH_TLS 168 [ERR_TLS_IO] = "TLS I/O error",
92 { ERR_TLS_ACTIVE, "Command not permitted when TLS active" }, 169 [ERR_LOGIN_DELAY] =
93 #endif /* WITH_TLS */ 170 "[LOGIN-DELAY] Attempt to log in within the minimum login delay interval",
94 { ERR_TLS_IO, "TLS I/O error" }, 171 [ERR_TERMINATE] = "Terminating on request",
95 { ERR_LOGIN_DELAY, 172 [ERR_SYS_LOGIN] = "[SYS/PERM] Cannot authenticate",
96 "[LOGIN-DELAY] Attempt to log in within the minimum login delay interval" },
97 { ERR_TERMINATE, "Terminating on request" },
98 { ERR_SYS_LOGIN, "[SYS/PERM] Cannot authenticate" },
99 { 0 }
100 }; 173 };
101 174
102 const char * 175 const char *
103 pop3d_error_string (int code) 176 pop3d_error_string (int code)
104 { 177 {
105 struct error_table *ep; 178 if (code >= 0 && code < MU_ARRAY_SIZE (error_table) && error_table[code])
106 for (ep = error_table; ep->code != 0; ep++) 179 return error_table[code];
107 if (ep->code == code)
108 return ep->text;
109 return "unknown error"; 180 return "unknown error";
110 } 181 }
......
...@@ -158,7 +158,7 @@ log_cipher (mu_stream_t stream) ...@@ -158,7 +158,7 @@ log_cipher (mu_stream_t stream)
158 } 158 }
159 159
160 void 160 void
161 pop3d_setio (int ifd, int ofd, int tls) 161 pop3d_setio (int ifd, int ofd, struct mu_tls_config *tls_conf)
162 { 162 {
163 mu_stream_t str, istream, ostream; 163 mu_stream_t str, istream, ostream;
164 164
...@@ -175,10 +175,12 @@ pop3d_setio (int ifd, int ofd, int tls) ...@@ -175,10 +175,12 @@ pop3d_setio (int ifd, int ofd, int tls)
175 pop3d_abquit (ERR_NO_OFILE); 175 pop3d_abquit (ERR_NO_OFILE);
176 176
177 /* Combine the two streams into an I/O one. */ 177 /* Combine the two streams into an I/O one. */
178 #ifdef WITH_TLS 178 if (tls_conf)
179 if (tls)
180 { 179 {
181 int rc = mu_tls_server_stream_create (&str, istream, ostream, 0); 180 int rc = mu_tls_stream_create (&str, istream, ostream,
181 tls_conf,
182 MU_TLS_SERVER,
183 0);
182 if (rc) 184 if (rc)
183 { 185 {
184 mu_stream_unref (istream); 186 mu_stream_unref (istream);
...@@ -186,12 +188,9 @@ pop3d_setio (int ifd, int ofd, int tls) ...@@ -186,12 +188,9 @@ pop3d_setio (int ifd, int ofd, int tls)
186 mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc)); 188 mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc));
187 pop3d_abquit (ERR_FILE); 189 pop3d_abquit (ERR_FILE);
188 } 190 }
189 tls_done = 1;
190 log_cipher (str); 191 log_cipher (str);
191 } 192 }
192 else 193 else if (mu_iostream_create (&str, istream, ostream))
193 #endif
194 if (mu_iostream_create (&str, istream, ostream))
195 pop3d_abquit (ERR_FILE); 194 pop3d_abquit (ERR_FILE);
196 195
197 /* Convert all writes to CRLF form. 196 /* Convert all writes to CRLF form.
...@@ -228,9 +227,8 @@ pop3d_setio (int ifd, int ofd, int tls) ...@@ -228,9 +227,8 @@ pop3d_setio (int ifd, int ofd, int tls)
228 } 227 }
229 } 228 }
230 229
231 #ifdef WITH_TLS
232 int 230 int
233 pop3d_init_tls_server () 231 pop3d_init_tls_server (struct mu_tls_config *tls_conf)
234 { 232 {
235 mu_stream_t tlsstream, stream[2]; 233 mu_stream_t tlsstream, stream[2];
236 int rc; 234 int rc;
...@@ -243,7 +241,10 @@ pop3d_init_tls_server () ...@@ -243,7 +241,10 @@ pop3d_init_tls_server ()
243 return 1; 241 return 1;
244 } 242 }
245 243
246 rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0); 244 rc = mu_tls_stream_create (&tlsstream, stream[0], stream[1],
245 tls_conf,
246 MU_TLS_SERVER,
247 0);
247 mu_stream_unref (stream[0]); 248 mu_stream_unref (stream[0]);
248 mu_stream_unref (stream[1]); 249 mu_stream_unref (stream[1]);
249 if (rc) 250 if (rc)
...@@ -263,7 +264,6 @@ pop3d_init_tls_server () ...@@ -263,7 +264,6 @@ pop3d_init_tls_server ()
263 } 264 }
264 return 0; 265 return 0;
265 } 266 }
266 #endif
267 267
268 void 268 void
269 pop3d_bye () 269 pop3d_bye ()
......
...@@ -37,15 +37,6 @@ int apop_database_safety = MU_FILE_SAFETY_ALL; ...@@ -37,15 +37,6 @@ int apop_database_safety = MU_FILE_SAFETY_ALL;
37 uid_t apop_database_owner; 37 uid_t apop_database_owner;
38 int apop_database_owner_set; 38 int apop_database_owner_set;
39 39
40 enum tls_mode tls_mode;
41
42 #ifdef WITH_TLS
43 int tls_available;
44 int tls_done;
45 #else
46 # define tls_available 0
47 #endif /* WITH_TLS */
48
49 int initial_state = AUTHORIZATION; 40 int initial_state = AUTHORIZATION;
50 41
51 /* Should all the messages be undeleted on startup */ 42 /* Should all the messages be undeleted on startup */
...@@ -169,13 +160,6 @@ cb_bulletin_db (void *data, mu_config_value_t *val) ...@@ -169,13 +160,6 @@ cb_bulletin_db (void *data, mu_config_value_t *val)
169 } 160 }
170 #endif 161 #endif
171 162
172 struct pop3d_srv_config
173 {
174 struct mu_srv_config m_cfg;
175 enum tls_mode tls_mode;
176 };
177
178 #ifdef WITH_TLS
179 static int 163 static int
180 cb_tls (void *data, mu_config_value_t *val) 164 cb_tls (void *data, mu_config_value_t *val)
181 { 165 {
...@@ -205,39 +189,14 @@ cb_tls (void *data, mu_config_value_t *val) ...@@ -205,39 +189,14 @@ cb_tls (void *data, mu_config_value_t *val)
205 return 0; 189 return 0;
206 } 190 }
207 191
208 static int
209 cb_tls_required (void *data, mu_config_value_t *val)
210 {
211 int bv;
212
213 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
214 return 1;
215 if (mu_str_to_c (val->v.string, mu_c_bool, &bv, NULL))
216 mu_error (_("Not a boolean value"));
217 else if (bv)
218 {
219 tls_mode = tls_required;
220 mu_diag_output (MU_DIAG_WARNING,
221 "the \"tls-required\" statement is deprecated, "
222 "use \"tls required\" instead");
223 }
224 else
225 mu_diag_output (MU_DIAG_WARNING,
226 "the \"tls-required\" statement is deprecated, "
227 "use \"tls\" instead");
228
229 return 0;
230 }
231 #endif
232
233 static struct mu_cfg_param pop3d_srv_param[] = { 192 static struct mu_cfg_param pop3d_srv_param[] = {
234 #ifdef WITH_TLS 193 { "tls-mode", mu_cfg_callback,
235 { "tls", mu_cfg_callback,
236 NULL, mu_offsetof (struct pop3d_srv_config, tls_mode), cb_tls, 194 NULL, mu_offsetof (struct pop3d_srv_config, tls_mode), cb_tls,
237 N_("Kind of TLS encryption to use for this server"), 195 N_("Kind of TLS encryption to use for this server"),
238 /* TRANSLATORS: words to the right of : are keywords - do not translate */ 196 /* TRANSLATORS: words to the right of : are keywords - do not translate */
239 N_("arg: false|true|ondemand|stls|requred|connection") }, 197 N_("arg: false|true|ondemand|stls|requred|connection") },
240 #endif 198 { "tls", mu_cfg_section,
199 NULL, mu_offsetof (struct pop3d_srv_config, tls_conf) },
241 { NULL } 200 { NULL }
242 }; 201 };
243 202
...@@ -272,16 +231,8 @@ static struct mu_cfg_param pop3d_cfg_param[] = { ...@@ -272,16 +231,8 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
272 " awrdir forbid files in world writable directories\n"), 231 " awrdir forbid files in world writable directories\n"),
273 N_("arg: list") }, 232 N_("arg: list") },
274 233
275 #ifdef WITH_TLS 234 { "tls", mu_cfg_section, &global_tls_conf },
276 { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls, 235
277 N_("Kind of TLS encryption to use"),
278 /* TRANSLATORS: words to the right of : are keywords - do not translate */
279 N_("arg: false|true|ondemand|stls|requred|connection") },
280 { "tls-required", mu_cfg_callback, &tls_mode, 0, cb_tls_required,
281 N_("Always require STLS before entering authentication phase.\n"
282 "Deprecated, use \"tls required\" instead."),
283 N_("arg: bool") },
284 #endif
285 #ifdef ENABLE_LOGIN_DELAY 236 #ifdef ENABLE_LOGIN_DELAY
286 { "login-delay", mu_c_time, &login_delay, 0, NULL, 237 { "login-delay", mu_c_time, &login_delay, 0, NULL,
287 N_("Set the minimal allowed delay between two successive logins.") }, 238 N_("Set the minimal allowed delay between two successive logins.") },
...@@ -355,7 +306,7 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs) ...@@ -355,7 +306,7 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs)
355 ofd -- output descriptor 306 ofd -- output descriptor
356 tls -- initiate encrypted connection */ 307 tls -- initiate encrypted connection */
357 int 308 int
358 pop3d_mainloop (int ifd, int ofd, enum tls_mode tls) 309 pop3d_mainloop (int ifd, int ofd, struct pop3d_srv_config *cfg)
359 { 310 {
360 int status = OK; 311 int status = OK;
361 char buffer[512]; 312 char buffer[512];
...@@ -365,24 +316,18 @@ pop3d_mainloop (int ifd, int ofd, enum tls_mode tls) ...@@ -365,24 +316,18 @@ pop3d_mainloop (int ifd, int ofd, enum tls_mode tls)
365 316
366 mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab)); 317 mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab));
367 318
368 if (tls == tls_unspecified) 319 pop3d_setio (ifd, ofd,
369 tls = tls_available ? tls_ondemand : tls_no; 320 cfg->tls_mode == tls_connection ? &cfg->tls_conf : NULL);
370 else if (tls != tls_no && !tls_available)
371 {
372 mu_error (_("TLS is not configured, but requested in the "
373 "configuration"));
374 tls = tls_no;
375 }
376
377 pop3d_setio (ifd, ofd, tls == tls_connection);
378 321
379 if (tls == tls_required) 322 if (cfg->tls_mode == tls_required)
380 initial_state = INITIAL; 323 initial_state = INITIAL;
381 324
382 state = tls == tls_connection ? AUTHORIZATION : initial_state; 325 state = cfg->tls_mode == tls_connection ? AUTHORIZATION : initial_state;
383 326
384 pop3d_session_init (&session); 327 pop3d_session_init (&session);
385 session.tls = tls; 328 session.tls_mode = cfg->tls_mode;
329 session.tls_conf = &cfg->tls_conf;
330
386 /* FIXME: state should also be in the session? */ 331 /* FIXME: state should also be in the session? */
387 332
388 /* Prepare the shared secret for APOP. */ 333 /* Prepare the shared secret for APOP. */
...@@ -528,8 +473,7 @@ pop3d_connection (int fd, struct sockaddr *sa, int salen, ...@@ -528,8 +473,7 @@ pop3d_connection (int fd, struct sockaddr *sa, int salen,
528 else 473 else
529 rc = 1; 474 rc = 1;
530 475
531 pop3d_mainloop (fd, fd, 476 pop3d_mainloop (fd, fd, cfg);
532 cfg->tls_mode == tls_unspecified ? tls_mode : cfg->tls_mode);
533 477
534 if (rc == 0) 478 if (rc == 0)
535 clr_strerr_flt (); 479 clr_strerr_flt ();
...@@ -569,6 +513,7 @@ main (int argc, char **argv) ...@@ -569,6 +513,7 @@ main (int argc, char **argv)
569 mu_tcpwrapper_cfg_init (); 513 mu_tcpwrapper_cfg_init ();
570 manlock_cfg_init (); 514 manlock_cfg_init ();
571 mu_acl_cfg_init (); 515 mu_acl_cfg_init ();
516 mu_tls_cfg_init ();
572 517
573 mu_m_server_create (&server, program_version); 518 mu_m_server_create (&server, program_version);
574 mu_m_server_set_config_size (server, sizeof (struct pop3d_srv_config)); 519 mu_m_server_set_config_size (server, sizeof (struct pop3d_srv_config));
...@@ -645,11 +590,7 @@ main (int argc, char **argv) ...@@ -645,11 +590,7 @@ main (int argc, char **argv)
645 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ 590 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
646 591
647 /* Check TLS environment, i.e. cert and key files */ 592 /* Check TLS environment, i.e. cert and key files */
648 #ifdef WITH_TLS 593 mu_m_server_set_preflight (server, stls_preflight);
649 tls_available = mu_check_tls_environment ();
650 if (tls_available)
651 enable_stls ();
652 #endif /* WITH_TLS */
653 594
654 /* Actually run the daemon. */ 595 /* Actually run the daemon. */
655 if (mu_m_server_mode (server) == MODE_DAEMON) 596 if (mu_m_server_mode (server) == MODE_DAEMON)
...@@ -661,9 +602,12 @@ main (int argc, char **argv) ...@@ -661,9 +602,12 @@ main (int argc, char **argv)
661 } 602 }
662 else 603 else
663 { 604 {
605 struct pop3d_srv_config cfg;
606 memset (&cfg, 0, sizeof cfg);
607 cfg.tls_mode = tls_no;
664 /* Make sure we are in the root directory. */ 608 /* Make sure we are in the root directory. */
665 chdir ("/"); 609 chdir ("/");
666 status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_mode); 610 status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, &cfg);
667 } 611 }
668 612
669 if (status) 613 if (status)
......
...@@ -145,31 +145,32 @@ extern int expire_on_exit; ...@@ -145,31 +145,32 @@ extern int expire_on_exit;
145 #define UPDATE 2 145 #define UPDATE 2
146 #define ABORT 3 146 #define ABORT 3
147 147
148 #define OK 0 148 enum pop3d_error {
149 #define ERR_WRONG_STATE 1 149 OK = 0,
150 #define ERR_BAD_ARGS 2 150 ERR_WRONG_STATE,
151 #define ERR_BAD_LOGIN 3 151 ERR_BAD_ARGS,
152 #define ERR_NO_MESG 4 152 ERR_BAD_LOGIN,
153 #define ERR_MESG_DELE 5 153 ERR_NO_MESG,
154 #define ERR_NOT_IMPL 6 154 ERR_MESG_DELE,
155 #define ERR_BAD_CMD 7 155 ERR_NOT_IMPL,
156 #define ERR_MBOX_LOCK 8 156 ERR_BAD_CMD,
157 #define ERR_TOO_LONG 9 157 ERR_MBOX_LOCK,
158 #define ERR_NO_MEM 10 158 ERR_TOO_LONG,
159 #define ERR_SIGNAL 11 159 ERR_NO_MEM,
160 #define ERR_FILE 12 160 ERR_SIGNAL,
161 #define ERR_NO_IFILE 13 161 ERR_FILE,
162 #define ERR_NO_OFILE 14 162 ERR_NO_IFILE,
163 #define ERR_IO 15 163 ERR_NO_OFILE,
164 #define ERR_PROTO 16 164 ERR_IO,
165 #define ERR_TIMEOUT 17 165 ERR_PROTO,
166 #define ERR_UNKNOWN 18 166 ERR_TIMEOUT,
167 #define ERR_MBOX_SYNC 19 167 ERR_UNKNOWN,
168 #define ERR_TLS_ACTIVE 20 168 ERR_MBOX_SYNC,
169 #define ERR_TLS_IO 21 169 ERR_TLS_IO,
170 #define ERR_LOGIN_DELAY 22 170 ERR_LOGIN_DELAY,
171 #define ERR_TERMINATE 23 171 ERR_TERMINATE,
172 #define ERR_SYS_LOGIN 24 172 ERR_SYS_LOGIN
173 };
173 174
174 enum tls_mode 175 enum tls_mode
175 { 176 {
...@@ -200,7 +201,15 @@ struct pop3d_capa ...@@ -200,7 +201,15 @@ struct pop3d_capa
200 struct pop3d_session 201 struct pop3d_session
201 { 202 {
202 mu_list_t capa; 203 mu_list_t capa;
203 enum tls_mode tls; 204 enum tls_mode tls_mode;
205 struct mu_tls_config *tls_conf;
206 };
207
208 struct pop3d_srv_config
209 {
210 struct mu_srv_config m_cfg;
211 enum tls_mode tls_mode;
212 struct mu_tls_config tls_conf;
204 }; 213 };
205 214
206 void pop3d_session_init (struct pop3d_session *session); 215 void pop3d_session_init (struct pop3d_session *session);
...@@ -227,10 +236,7 @@ extern char *md5shared; ...@@ -227,10 +236,7 @@ extern char *md5shared;
227 extern size_t children; 236 extern size_t children;
228 extern struct daemon_param daemon_param; 237 extern struct daemon_param daemon_param;
229 extern int debug_mode; 238 extern int debug_mode;
230 #ifdef WITH_TLS 239
231 extern int tls_available;
232 extern int tls_done;
233 #endif /* WITH_TLS */
234 extern int undelete_on_startup; 240 extern int undelete_on_startup;
235 extern struct mu_auth_data *auth_data; 241 extern struct mu_auth_data *auth_data;
236 extern unsigned int idle_timeout; 242 extern unsigned int idle_timeout;
...@@ -242,6 +248,8 @@ extern int apop_database_safety; ...@@ -242,6 +248,8 @@ extern int apop_database_safety;
242 extern uid_t apop_database_owner; 248 extern uid_t apop_database_owner;
243 extern int apop_database_owner_set; 249 extern int apop_database_owner_set;
244 250
251 extern struct mu_tls_config global_tls_conf;
252
245 /* Safety checks for group-rw database files, such as stat and bulletin 253 /* Safety checks for group-rw database files, such as stat and bulletin
246 databases */ 254 databases */
247 255
...@@ -282,13 +290,12 @@ extern void pop3d_parse_command (char *cmd, char **pcmd, char **parg); ...@@ -282,13 +290,12 @@ extern void pop3d_parse_command (char *cmd, char **pcmd, char **parg);
282 extern RETSIGTYPE pop3d_master_signal (int); 290 extern RETSIGTYPE pop3d_master_signal (int);
283 extern RETSIGTYPE pop3d_child_signal (int); 291 extern RETSIGTYPE pop3d_child_signal (int);
284 292
285 #ifdef WITH_TLS
286 extern int pop3d_stls (char *, struct pop3d_session *); 293 extern int pop3d_stls (char *, struct pop3d_session *);
287 extern void enable_stls (void); 294 int stls_preflight (mu_m_server_t msrv);
288 #endif /* WITH_TLS */ 295
289 extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2); 296 extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2);
290 297
291 extern void pop3d_setio (int, int, int); 298 extern void pop3d_setio (int, int, struct mu_tls_config *);
292 extern char *pop3d_readline (char *, size_t); 299 extern char *pop3d_readline (char *, size_t);
293 extern void pop3d_flush_output (void); 300 extern void pop3d_flush_output (void);
294 301
...@@ -299,10 +306,7 @@ extern int pop3d_is_deleted (mu_attribute_t attr); ...@@ -299,10 +306,7 @@ extern int pop3d_is_deleted (mu_attribute_t attr);
299 extern void pop3d_unset_deleted (mu_attribute_t attr); 306 extern void pop3d_unset_deleted (mu_attribute_t attr);
300 void pop3d_undelete_all (void); 307 void pop3d_undelete_all (void);
301 308
302 #ifdef WITH_TLS 309 extern int pop3d_init_tls_server (struct mu_tls_config *tls_conf);
303 extern int pop3d_init_tls_server (void);
304 extern void pop3d_deinit_tls_server (void);
305 #endif /* WITH_TLS */
306 310
307 extern void pop3d_mark_retr (mu_attribute_t attr); 311 extern void pop3d_mark_retr (mu_attribute_t attr);
308 extern int pop3d_is_retr (mu_attribute_t attr); 312 extern int pop3d_is_retr (mu_attribute_t attr);
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
19 19
20 /* STLS command -- TLS/SSL encryption */ 20 /* STLS command -- TLS/SSL encryption */
21 21
22 #ifdef WITH_TLS
23
24 int 22 int
25 pop3d_stls (char *arg, struct pop3d_session *session) 23 pop3d_stls (char *arg, struct pop3d_session *session)
26 { 24 {
...@@ -30,7 +28,7 @@ pop3d_stls (char *arg, struct pop3d_session *session) ...@@ -30,7 +28,7 @@ pop3d_stls (char *arg, struct pop3d_session *session)
30 if (state != initial_state) 28 if (state != initial_state)
31 return ERR_WRONG_STATE; 29 return ERR_WRONG_STATE;
32 30
33 switch (session->tls) 31 switch (session->tls_mode)
34 { 32 {
35 case tls_ondemand: 33 case tls_ondemand:
36 case tls_required: 34 case tls_required:
...@@ -39,26 +37,20 @@ pop3d_stls (char *arg, struct pop3d_session *session) ...@@ -39,26 +37,20 @@ pop3d_stls (char *arg, struct pop3d_session *session)
39 return ERR_WRONG_STATE; 37 return ERR_WRONG_STATE;
40 } 38 }
41 39
42 if (tls_done)
43 return ERR_TLS_ACTIVE;
44
45 pop3d_outf ("+OK Begin TLS negotiation\n"); 40 pop3d_outf ("+OK Begin TLS negotiation\n");
46 pop3d_flush_output (); 41 pop3d_flush_output ();
47 42
48 tls_done = pop3d_init_tls_server () == 0; 43 if (pop3d_init_tls_server (session->tls_conf))
49
50 if (!tls_done)
51 { 44 {
52 mu_diag_output (MU_DIAG_ERROR, _("Session terminated")); 45 mu_diag_output (MU_DIAG_ERROR, _("Session terminated"));
53 state = ABORT; 46 state = ABORT;
54 return ERR_UNKNOWN; 47 return ERR_UNKNOWN;
55 } 48 }
56 49
50 session->tls_mode = tls_no;
57 state = AUTHORIZATION; /* Confirm we're in this state. Necessary for 51 state = AUTHORIZATION; /* Confirm we're in this state. Necessary for
58 "tls required" to work */ 52 "tls required" to work */
59 53
60 return OK; 54 return OK;
61 } 55 }
62 56
63 #endif /* WITH_TLS */
64
......