Commit 6b97e35b 6b97e35bebf12ea2a4e2d47a2c056ef53e46bd3d by Wojciech Polak

Added TLS/SSL support (via GnuTLS)

1 parent 3311ee56
1 ## Process this file with GNU Automake to create Makefile.in 1 ## Process this file with GNU Automake to create Makefile.in
2 2
3 ## Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 3 ## Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 ## 4 ##
5 ## GNU Mailtuils is free software; you can redistribute it and/or 5 ## GNU Mailutils is free software; you can redistribute it and/or
6 ## modify it under the terms of the GNU General Public License as 6 ## modify it under the terms of the GNU General Public License as
7 ## published by the Free Software Foundation; either version 2, or (at 7 ## published by the Free Software Foundation; either version 2, or (at
8 ## your option) any later version. 8 ## your option) any later version.
9 ## 9 ##
10 ## This program is distributed in the hope that it will be useful, but 10 ## GNU Mailutils is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of 11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details. 13 ## General Public License for more details.
14 ## 14 ##
15 ## You should have received a copy of the GNU General Public License 15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software 16 ## along with GNU Mailutils; if not, write to the Free Software
17 ## Foundation, Inc. 17 ## Foundation, Inc.
18 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19
...@@ -26,8 +26,8 @@ imap4d_LDADD = @AUTHOBJS@ ../mailbox/libmailbox.la @AUTHLIBS@ ../lib/libmailuti ...@@ -26,8 +26,8 @@ imap4d_LDADD = @AUTHOBJS@ ../mailbox/libmailbox.la @AUTHLIBS@ ../lib/libmailuti
26 imap4d_SOURCES = append.c authenticate.c bye.c capability.c check.c close.c \ 26 imap4d_SOURCES = append.c authenticate.c bye.c capability.c check.c close.c \
27 commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d.c \ 27 commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d.c \
28 imap4d.h list.c logout.c login.c lsub.c namespace.c noop.c rename.c search.c \ 28 imap4d.h list.c logout.c login.c lsub.c namespace.c noop.c rename.c search.c \
29 select.c signal.c status.c store.c subscribe.c sync.c uid.c unsubscribe.c \ 29 select.c signal.c starttls.c status.c store.c subscribe.c sync.c uid.c \
30 util.c version.c 30 unsubscribe.c util.c version.c
31 31
32 ## This kludge is necessary to correctly establish imap4d -> AUTHOBJS 32 ## This kludge is necessary to correctly establish imap4d -> AUTHOBJS
33 ## dependency. Think about better approach --gray 33 ## dependency. Think about better approach --gray
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 /* GSSAPI authentication for imap (rfc 1731). 18 /*
19 GSSAPI authentication for imap (rfc 1731).
19 */ 20 */
20 21
21 #include "imap4d.h" 22 #include "imap4d.h"
...@@ -46,11 +47,8 @@ display_status_1 (char *m, OM_uint32 code, int type) ...@@ -46,11 +47,8 @@ display_status_1 (char *m, OM_uint32 code, int type)
46 do 47 do
47 { 48 {
48 maj_stat = gss_display_status (&min_stat, code, 49 maj_stat = gss_display_status (&min_stat, code,
49 type, GSS_C_NULL_OID, 50 type, GSS_C_NULL_OID, &msg_ctx, &msg);
50 &msg_ctx, &msg); 51 syslog (LOG_ERR, _("GSS-API error %s: %s\n"), m, (char *) msg.value);
51 syslog (LOG_ERR,
52 _("GSS-API error %s: %s\n"), m,
53 (char *)msg.value);
54 gss_release_buffer (&min_stat, &msg); 52 gss_release_buffer (&min_stat, &msg);
55 } 53 }
56 while (msg_ctx); 54 while (msg_ctx);
...@@ -64,14 +62,14 @@ display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) ...@@ -64,14 +62,14 @@ display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
64 } 62 }
65 63
66 static int 64 static int
67 imap4d_gss_userok(gss_buffer_t client_name, char *name) 65 imap4d_gss_userok (gss_buffer_t client_name, char *name)
68 { 66 {
69 int rc = -1; 67 int rc = -1;
70 krb5_principal p; 68 krb5_principal p;
71 krb5_context kcontext; 69 krb5_context kcontext;
72 70
73 krb5_init_context (&kcontext); 71 krb5_init_context (&kcontext);
74 72
75 if (krb5_parse_name (kcontext, client_name->value, &p) != 0) 73 if (krb5_parse_name (kcontext, client_name->value, &p) != 0)
76 return -1; 74 return -1;
77 if (krb5_kuserok (kcontext, p, name)) 75 if (krb5_kuserok (kcontext, p, name))
...@@ -99,57 +97,54 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -99,57 +97,54 @@ auth_gssapi (struct imap4d_command *command, char **username)
99 gss_qop_t quality; 97 gss_qop_t quality;
100 gss_name_t client; 98 gss_name_t client;
101 gss_buffer_desc client_name; 99 gss_buffer_desc client_name;
102 100
103 /* Obtain server credentials. RFC 1732 states, that 101 /* Obtain server credentials. RFC 1732 states, that
104 "The server must issue a ready response with no data and pass the 102 "The server must issue a ready response with no data and pass the
105 resulting client supplied token to GSS_Accept_sec_context as 103 resulting client supplied token to GSS_Accept_sec_context as
106 input_token, setting acceptor_cred_handle to NULL (for "use default 104 input_token, setting acceptor_cred_handle to NULL (for "use default
107 credentials"), and 0 for input_context_handle (initially)." 105 credentials"), and 0 for input_context_handle (initially)."
108 In MIT implementation, passing NULL as acceptor_cred_handle won't 106 In MIT implementation, passing NULL as acceptor_cred_handle won't
109 work (possibly due to a bug in krb5_gss_accept_sec_context()), so 107 work (possibly due to a bug in krb5_gss_accept_sec_context()), so
110 we acquire server credentials explicitly. */ 108 we acquire server credentials explicitly. */
111 109
112 asprintf ((char**)&tmp, "imap@%s", util_localname ()); 110 asprintf ((char **) &tmp, "imap@%s", util_localname ());
113 tokbuf.value = tmp; 111 tokbuf.value = tmp;
114 tokbuf.length = strlen (tokbuf.value) + 1; 112 tokbuf.length = strlen (tokbuf.value) + 1;
115 maj_stat = gss_import_name (&min_stat, &tokbuf, 113 maj_stat = gss_import_name (&min_stat, &tokbuf,
116 gss_nt_service_name, 114 gss_nt_service_name, &server_name);
117 &server_name);
118 if (maj_stat != GSS_S_COMPLETE) 115 if (maj_stat != GSS_S_COMPLETE)
119 { 116 {
120 display_status ("import name", maj_stat, min_stat); 117 display_status ("import name", maj_stat, min_stat);
121 util_finish (command, RESP_NO, 118 util_finish (command, RESP_NO, "GSSAPI authentication not available");
122 "GSSAPI authentication not available");
123 return 1; 119 return 1;
124 } 120 }
125 121
126 maj_stat = gss_acquire_cred (&min_stat, server_name, 0, 122 maj_stat = gss_acquire_cred (&min_stat, server_name, 0,
127 GSS_C_NULL_OID_SET, GSS_C_ACCEPT, 123 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
128 &server_creds, NULL, NULL); 124 &server_creds, NULL, NULL);
129 gss_release_name(&min_stat2, &server_name); 125 gss_release_name (&min_stat2, &server_name);
130 126
131 if (maj_stat != GSS_S_COMPLETE) 127 if (maj_stat != GSS_S_COMPLETE)
132 { 128 {
133 display_status ("acquire credentials", maj_stat, min_stat); 129 display_status ("acquire credentials", maj_stat, min_stat);
134 util_finish (command, RESP_NO, 130 util_finish (command, RESP_NO, "GSSAPI authentication not available");
135 "GSSAPI authentication not available");
136 return 1; 131 return 1;
137 } 132 }
138 133
139 /* Start the dialogue */ 134 /* Start the dialogue */
140 135
141 util_send ("+ GO AHEAD\r\n"); 136 util_send ("+ GO AHEAD\r\n");
142 137
143 context = GSS_C_NO_CONTEXT; 138 context = GSS_C_NO_CONTEXT;
144 139
145 for (;;) 140 for (;;)
146 { 141 {
147 token_str = imap4d_readline_ex (ifile); 142 token_str = imap4d_readline_ex ();
148 util_base64_decode (token_str, strlen (token_str), &tmp, &size); 143 util_base64_decode (token_str, strlen (token_str), &tmp, &size);
149 tokbuf.value = tmp; 144 tokbuf.value = tmp;
150 tokbuf.length = size; 145 tokbuf.length = size;
151 free (token_str); 146 free (token_str);
152 147
153 maj_stat = gss_accept_sec_context (&min_stat, 148 maj_stat = gss_accept_sec_context (&min_stat,
154 &context, 149 &context,
155 server_creds, 150 server_creds,
...@@ -158,9 +153,7 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -158,9 +153,7 @@ auth_gssapi (struct imap4d_command *command, char **username)
158 &client, 153 &client,
159 &mech_type, 154 &mech_type,
160 &outbuf, 155 &outbuf,
161 &cflags, 156 &cflags, NULL, &cred_handle);
162 NULL,
163 &cred_handle);
164 free (tmp); 157 free (tmp);
165 if (maj_stat == GSS_S_CONTINUE_NEEDED) 158 if (maj_stat == GSS_S_CONTINUE_NEEDED)
166 { 159 {
...@@ -176,12 +169,11 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -176,12 +169,11 @@ auth_gssapi (struct imap4d_command *command, char **username)
176 else if (maj_stat == GSS_S_COMPLETE) 169 else if (maj_stat == GSS_S_COMPLETE)
177 break; 170 break;
178 /* Bail out otherwise */ 171 /* Bail out otherwise */
179 172
180 display_status ("accept context", maj_stat, min_stat); 173 display_status ("accept context", maj_stat, min_stat);
181 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); 174 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
182 gss_release_buffer (&min_stat, &outbuf); 175 gss_release_buffer (&min_stat, &outbuf);
183 util_finish (command, RESP_NO, 176 util_finish (command, RESP_NO, "GSSAPI authentication failed");
184 "GSSAPI authentication failed");
185 return 1; 177 return 1;
186 } 178 }
187 179
...@@ -191,7 +183,7 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -191,7 +183,7 @@ auth_gssapi (struct imap4d_command *command, char **username)
191 util_send ("+ %*.*s\r\n", size, size, tmp); 183 util_send ("+ %*.*s\r\n", size, size, tmp);
192 free (tmp); 184 free (tmp);
193 gss_release_buffer (&min_stat, &outbuf); 185 gss_release_buffer (&min_stat, &outbuf);
194 token_str = imap4d_readline_ex (ifile); 186 token_str = imap4d_readline_ex ();
195 free (token_str); 187 free (token_str);
196 } 188 }
197 189
...@@ -205,15 +197,15 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -205,15 +197,15 @@ auth_gssapi (struct imap4d_command *command, char **username)
205 util_send ("+ %*.*s\r\n", size, size, tmp); 197 util_send ("+ %*.*s\r\n", size, size, tmp);
206 free (tmp); 198 free (tmp);
207 199
208 token_str = imap4d_readline_ex (ifile); 200 token_str = imap4d_readline_ex ();
209 util_base64_decode (token_str, strlen (token_str), 201 util_base64_decode (token_str, strlen (token_str),
210 (unsigned char **)&tokbuf.value, &tokbuf.length); 202 (unsigned char **) &tokbuf.value, &tokbuf.length);
211 free (token_str); 203 free (token_str);
212 204
213 gss_unwrap (&min_stat, context, &tokbuf, &outbuf, &cflags, &quality); 205 gss_unwrap (&min_stat, context, &tokbuf, &outbuf, &cflags, &quality);
214 free (tokbuf.value); 206 free (tokbuf.value);
215 207
216 sec_level = ntohl (*(OM_uint32*)outbuf.value); 208 sec_level = ntohl (*(OM_uint32 *) outbuf.value);
217 209
218 /* FIXME: parse sec_level and act accordingly to its settings */ 210 /* FIXME: parse sec_level and act accordingly to its settings */
219 mech = sec_level >> 24; 211 mech = sec_level >> 24;
...@@ -226,25 +218,23 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -226,25 +218,23 @@ auth_gssapi (struct imap4d_command *command, char **username)
226 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); 218 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
227 gss_release_buffer (&min_stat, &outbuf); 219 gss_release_buffer (&min_stat, &outbuf);
228 util_finish (command, RESP_NO, 220 util_finish (command, RESP_NO,
229 "GSSAPI authentication failed: unsupported protection mechanism"); 221 "GSSAPI authentication failed: unsupported protection mechanism");
230 return 1; 222 return 1;
231 } 223 }
232 protection_mech = mech; 224 protection_mech = mech;
233 client_buffer_size = sec_level & 0x00ffffffff; 225 client_buffer_size = sec_level & 0x00ffffffff;
234 226
235 *username = strdup ((char*)outbuf.value + 4); 227 *username = strdup ((char *) outbuf.value + 4);
236 gss_release_buffer (&min_stat, &outbuf); 228 gss_release_buffer (&min_stat, &outbuf);
237 229
238 maj_stat = gss_display_name(&min_stat, client, 230 maj_stat = gss_display_name (&min_stat, client, &client_name, &mech_type);
239 &client_name, &mech_type);
240 if (maj_stat != GSS_S_COMPLETE) 231 if (maj_stat != GSS_S_COMPLETE)
241 { 232 {
242 display_status ("get client name", maj_stat, min_stat); 233 display_status ("get client name", maj_stat, min_stat);
243 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); 234 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
244 gss_release_buffer (&min_stat, &outbuf); 235 gss_release_buffer (&min_stat, &outbuf);
245 free (*username); 236 free (*username);
246 util_finish (command, RESP_NO, 237 util_finish (command, RESP_NO, "GSSAPI authentication failed");
247 "GSSAPI authentication failed");
248 return 1; 238 return 1;
249 } 239 }
250 240
...@@ -270,8 +260,6 @@ auth_gssapi (struct imap4d_command *command, char **username) ...@@ -270,8 +260,6 @@ auth_gssapi (struct imap4d_command *command, char **username)
270 gss_release_buffer (&min_stat, &client_name); 260 gss_release_buffer (&min_stat, &client_name);
271 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf); 261 maj_stat = gss_delete_sec_context (&min_stat, &context, &outbuf);
272 gss_release_buffer (&min_stat, &outbuf); 262 gss_release_buffer (&min_stat, &outbuf);
273 util_finish (command, RESP_OK, 263 util_finish (command, RESP_OK, "GSSAPI authentication successful");
274 "GSSAPI authentication successful");
275 return 0; 264 return 0;
276 } 265 }
277
......
...@@ -44,7 +44,7 @@ imap4d_bye0 (int reason, struct imap4d_command *command) ...@@ -44,7 +44,7 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
44 break; 44 break;
45 45
46 case ERR_SIGNAL: 46 case ERR_SIGNAL:
47 if (ofile) 47 if (util_is_ofile())
48 util_out (RESP_BYE, "Quitting on signal"); 48 util_out (RESP_BYE, "Quitting on signal");
49 syslog (LOG_ERR, _("Quitting on signal")); 49 syslog (LOG_ERR, _("Quitting on signal"));
50 break; 50 break;
...@@ -78,6 +78,14 @@ imap4d_bye0 (int reason, struct imap4d_command *command) ...@@ -78,6 +78,14 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
78 78
79 if (status == EXIT_SUCCESS && command) 79 if (status == EXIT_SUCCESS && command)
80 util_finish (command, RESP_OK, "Completed"); 80 util_finish (command, RESP_OK, "Completed");
81
82 #ifdef WITH_TLS
83 if (tls_done)
84 imap4d_deinit_tls_server ();
85 if (tls_available)
86 mu_deinit_tls_libs ();
87 #endif /* WITH_TLS */
88
81 closelog (); 89 closelog ();
82 exit (status); 90 exit (status);
83 } 91 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
...@@ -28,13 +28,20 @@ int ...@@ -28,13 +28,20 @@ int
28 imap4d_capability (struct imap4d_command *command, char *arg) 28 imap4d_capability (struct imap4d_command *command, char *arg)
29 { 29 {
30 int i; 30 int i;
31 31
32 (void)arg; 32 (void) arg;
33 util_send ("* CAPABILITY"); 33 util_send ("* CAPABILITY");
34
34 for (i = 0; capa[i]; i++) 35 for (i = 0; capa[i]; i++)
35 util_send(" %s", capa[i]); 36 util_send (" %s", capa[i]);
37
38 #ifdef WITH_TLS
39 if (tls_available)
40 util_send (" STARTTLS");
41 #endif /* WITH_TLS */
42
36 imap4d_auth_capability (); 43 imap4d_auth_capability ();
37 util_send("\r\n"); 44 util_send ("\r\n");
38 45
39 return util_finish (command, RESP_OK, "Completed"); 46 return util_finish (command, RESP_OK, "Completed");
40 } 47 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
...@@ -45,5 +45,8 @@ struct imap4d_command imap4d_command_table [] = ...@@ -45,5 +45,8 @@ struct imap4d_command imap4d_command_table [] =
45 { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 45 { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
46 { "NAMESPACE", imap4d_namespace, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 46 { "NAMESPACE", imap4d_namespace, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
47 { "X-VERSION", imap4d_version, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL }, 47 { "X-VERSION", imap4d_version, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
48 #ifdef WITH_TLS
49 { "STARTTLS", imap4d_starttls, STATE_NONAUTH, STATE_NONE, STATE_NONE, NULL },
50 #endif /* WITH_TLS */
48 { NULL, 0, 0, 0, 0, NULL } 51 { NULL, 0, 0, 0, 0, NULL }
49 }; 52 };
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,47 +13,50 @@ ...@@ -13,47 +13,50 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
20 FILE *ifile;
21 FILE *ofile;
22 mailbox_t mbox; 20 mailbox_t mbox;
23 char *homedir; 21 char *homedir;
24 int state = STATE_NONAUTH; 22 int state = STATE_NONAUTH;
25 int debug_mode = 0; 23 int debug_mode = 0;
26 struct mu_auth_data *auth_data; 24 struct mu_auth_data *auth_data;
27 25
28 struct daemon_param daemon_param = { 26 struct daemon_param daemon_param = {
29 MODE_INTERACTIVE, /* Start in interactive (inetd) mode */ 27 MODE_INTERACTIVE, /* Start in interactive (inetd) mode */
30 20, /* Default maximum number of children */ 28 20, /* Default maximum number of children */
31 143, /* Standard IMAP4 port */ 29 143, /* Standard IMAP4 port */
32 1800, /* RFC2060: 30 minutes. */ 30 1800, /* RFC2060: 30 minutes. */
33 0 /* No transcript by default */ 31 0 /* No transcript by default */
34 }; 32 };
35 33
34 #ifdef WITH_TLS
35 int tls_available;
36 int tls_done;
37 #endif /* WITH_TLS */
38
36 /* Number of child processes. */ 39 /* Number of child processes. */
37 volatile size_t children; 40 volatile size_t children;
38 41
39 const char *argp_program_version = "imap4d (" PACKAGE_STRING ")"; 42 const char *argp_program_version = "imap4d (" PACKAGE_STRING ")";
40 static char doc[] = N_("GNU imap4d -- the IMAP4D daemon"); 43 static char doc[] = N_("GNU imap4d -- the IMAP4D daemon");
41 44
42 static struct argp_option options[] = 45 static struct argp_option options[] = {
43 {
44 {"other-namespace", 'O', N_("PATHLIST"), 0, 46 {"other-namespace", 'O', N_("PATHLIST"), 0,
45 N_("set the `other' namespace"), 0}, 47 N_("set the `other' namespace"), 0},
46 {"shared-namespace", 'S', N_("PATHLIST"), 0, 48 {"shared-namespace", 'S', N_("PATHLIST"), 0,
47 N_("set the `shared' namespace"), 0}, 49 N_("set the `shared' namespace"), 0},
48 { NULL, 0, NULL, 0, NULL, 0 } 50 {NULL, 0, NULL, 0, NULL, 0}
49 }; 51 };
50 52
51 static error_t imap4d_parse_opt (int key, char *arg, struct argp_state *state); 53 static error_t imap4d_parse_opt (int key, char *arg,
54 struct argp_state *state);
52 55
53 static struct argp argp = { 56 static struct argp argp = {
54 options, 57 options,
55 imap4d_parse_opt, 58 imap4d_parse_opt,
56 NULL, 59 NULL,
57 doc, 60 doc,
58 NULL, 61 NULL,
59 NULL, NULL 62 NULL, NULL
...@@ -62,6 +65,9 @@ static struct argp argp = { ...@@ -62,6 +65,9 @@ static struct argp argp = {
62 static const char *imap4d_capa[] = { 65 static const char *imap4d_capa[] = {
63 "daemon", 66 "daemon",
64 "auth", 67 "auth",
68 #ifdef WITH_TLS
69 "tls",
70 #endif /* WITH_TLS */
65 "common", 71 "common",
66 "mailbox", 72 "mailbox",
67 "logging", 73 "logging",
...@@ -69,10 +75,10 @@ static const char *imap4d_capa[] = { ...@@ -69,10 +75,10 @@ static const char *imap4d_capa[] = {
69 NULL 75 NULL
70 }; 76 };
71 77
72 static int imap4d_mainloop __P ((int, int)); 78 static int imap4d_mainloop __P ((int, int));
73 static void imap4d_daemon_init __P ((void)); 79 static void imap4d_daemon_init __P ((void));
74 static void imap4d_daemon __P ((unsigned int, unsigned int)); 80 static void imap4d_daemon __P ((unsigned int, unsigned int));
75 static int imap4d_mainloop __P ((int, int)); 81 static int imap4d_mainloop __P ((int, int));
76 82
77 static error_t 83 static error_t
78 imap4d_parse_opt (int key, char *arg, struct argp_state *state) 84 imap4d_parse_opt (int key, char *arg, struct argp_state *state)
...@@ -82,15 +88,15 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -82,15 +88,15 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state)
82 case ARGP_KEY_INIT: 88 case ARGP_KEY_INIT:
83 state->child_inputs[0] = state->input; 89 state->child_inputs[0] = state->input;
84 break; 90 break;
85 91
86 case 'O': 92 case 'O':
87 set_namespace (NS_OTHER, arg); 93 set_namespace (NS_OTHER, arg);
88 break; 94 break;
89 95
90 case 'S': 96 case 'S':
91 set_namespace (NS_SHARED, arg); 97 set_namespace (NS_SHARED, arg);
92 break; 98 break;
93 99
94 default: 100 default:
95 return ARGP_ERR_UNKNOWN; 101 return ARGP_ERR_UNKNOWN;
96 } 102 }
...@@ -106,9 +112,12 @@ main (int argc, char **argv) ...@@ -106,9 +112,12 @@ main (int argc, char **argv)
106 /* Native Language Support */ 112 /* Native Language Support */
107 mu_init_nls (); 113 mu_init_nls ();
108 114
109 state = STATE_NONAUTH; /* Starting state in non-auth. */ 115 state = STATE_NONAUTH; /* Starting state in non-auth. */
110 116
111 MU_AUTH_REGISTER_ALL_MODULES(); 117 MU_AUTH_REGISTER_ALL_MODULES ();
118 #ifdef WITH_TLS
119 mu_tls_init_argp ();
120 #endif /* WITH_TLS */
112 mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa, NULL, &daemon_param); 121 mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa, NULL, &daemon_param);
113 122
114 #ifdef USE_LIBPAM 123 #ifdef USE_LIBPAM
...@@ -131,7 +140,7 @@ main (int argc, char **argv) ...@@ -131,7 +140,7 @@ main (int argc, char **argv)
131 perror (_("Error getting mail group")); 140 perror (_("Error getting mail group"));
132 exit (1); 141 exit (1);
133 } 142 }
134 143
135 if (setgid (gr->gr_gid) == -1) 144 if (setgid (gr->gr_gid) == -1)
136 { 145 {
137 perror (_("Error setting mail group")); 146 perror (_("Error setting mail group"));
...@@ -143,7 +152,7 @@ main (int argc, char **argv) ...@@ -143,7 +152,7 @@ main (int argc, char **argv)
143 { 152 {
144 list_t bookie; 153 list_t bookie;
145 registrar_get_list (&bookie); 154 registrar_get_list (&bookie);
146 list_append (bookie, mbox_record); 155 list_append (bookie, mbox_record);
147 list_append (bookie, path_record); 156 list_append (bookie, path_record);
148 } 157 }
149 158
...@@ -174,8 +183,15 @@ main (int argc, char **argv) ...@@ -174,8 +183,15 @@ main (int argc, char **argv)
174 /* Redirect any stdout error from the library to syslog, they 183 /* Redirect any stdout error from the library to syslog, they
175 should not go to the client. */ 184 should not go to the client. */
176 mu_error_set_print (mu_syslog_error_printer); 185 mu_error_set_print (mu_syslog_error_printer);
177 186
178 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ 187 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
188
189 /* Check TLS environment, i.e. cert and key files */
190 #ifdef WITH_TLS
191 tls_available = mu_check_tls_environment ();
192 if (tls_available)
193 tls_available = mu_init_tls_libs ();
194 #endif /* WITH_TLS */
179 195
180 /* Actually run the daemon. */ 196 /* Actually run the daemon. */
181 if (daemon_param.mode == MODE_DAEMON) 197 if (daemon_param.mode == MODE_DAEMON)
...@@ -194,18 +210,13 @@ static int ...@@ -194,18 +210,13 @@ static int
194 imap4d_mainloop (int infile, int outfile) 210 imap4d_mainloop (int infile, int outfile)
195 { 211 {
196 char *text; 212 char *text;
197 213
198 /* Reset hup to exit. */ 214 /* Reset hup to exit. */
199 signal (SIGHUP, imap4d_signal); 215 signal (SIGHUP, imap4d_signal);
200 /* Timeout alarm. */ 216 /* Timeout alarm. */
201 signal (SIGALRM, imap4d_signal); 217 signal (SIGALRM, imap4d_signal);
202 218
203 ifile = fdopen (infile, "r"); 219 util_setio (infile, outfile);
204 ofile = fdopen (outfile, "w");
205 if (!ofile || !ifile)
206 imap4d_bye (ERR_NO_OFILE);
207
208 setvbuf(ofile, NULL, _IOLBF, 0);
209 220
210 /* log information on the connecting client */ 221 /* log information on the connecting client */
211 if (!debug_mode) 222 if (!debug_mode)
...@@ -214,11 +225,11 @@ imap4d_mainloop (int infile, int outfile) ...@@ -214,11 +225,11 @@ imap4d_mainloop (int infile, int outfile)
214 int len = sizeof cs; 225 int len = sizeof cs;
215 226
216 syslog (LOG_INFO, _("Incoming connection opened")); 227 syslog (LOG_INFO, _("Incoming connection opened"));
217 if (getpeername (infile, (struct sockaddr*)&cs, &len) < 0) 228 if (getpeername (infile, (struct sockaddr *) &cs, &len) < 0)
218 syslog (LOG_ERR, _("can't obtain IP address of client: %s"), 229 syslog (LOG_ERR, _("can't obtain IP address of client: %s"),
219 strerror (errno)); 230 strerror (errno));
220 else 231 else
221 syslog (LOG_INFO, _("connect from %s"), inet_ntoa(cs.sin_addr)); 232 syslog (LOG_INFO, _("connect from %s"), inet_ntoa (cs.sin_addr));
222 text = "IMAP4rev1"; 233 text = "IMAP4rev1";
223 } 234 }
224 else 235 else
...@@ -226,23 +237,22 @@ imap4d_mainloop (int infile, int outfile) ...@@ -226,23 +237,22 @@ imap4d_mainloop (int infile, int outfile)
226 syslog (LOG_INFO, _("Started in debugging mode")); 237 syslog (LOG_INFO, _("Started in debugging mode"));
227 text = "IMAP4rev1 Debugging mode"; 238 text = "IMAP4rev1 Debugging mode";
228 } 239 }
229 240
230 /* Greetings. */ 241 /* Greetings. */
231 util_out (RESP_OK, text); 242 util_out (RESP_OK, text);
232 fflush (ofile); 243 util_flush_output ();
233 244
234 while (1) 245 while (1)
235 { 246 {
236 char *cmd = imap4d_readline (ifile); 247 char *cmd = imap4d_readline ();
237 /* check for updates */ 248 /* check for updates */
238 imap4d_sync (); 249 imap4d_sync ();
239 util_do_command (cmd); 250 util_do_command (cmd);
240 imap4d_sync (); 251 imap4d_sync ();
241 free (cmd); 252 free (cmd);
242 fflush (ofile); 253 util_flush_output ();
243 } 254 }
244 255
245 closelog ();
246 return EXIT_SUCCESS; 256 return EXIT_SUCCESS;
247 } 257 }
248 258
...@@ -256,7 +266,7 @@ imap4d_daemon_init (void) ...@@ -256,7 +266,7 @@ imap4d_daemon_init (void)
256 first three one, in, out, err */ 266 first three one, in, out, err */
257 if (daemon (0, 0) < 0) 267 if (daemon (0, 0) < 0)
258 { 268 {
259 perror(_("fork failed:")); 269 perror (_("fork failed:"));
260 exit (1); 270 exit (1);
261 } 271 }
262 272
...@@ -289,18 +299,18 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -289,18 +299,18 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port)
289 listenfd = socket (AF_INET, SOCK_STREAM, 0); 299 listenfd = socket (AF_INET, SOCK_STREAM, 0);
290 if (listenfd == -1) 300 if (listenfd == -1)
291 { 301 {
292 syslog (LOG_ERR, "socket: %s", strerror(errno)); 302 syslog (LOG_ERR, "socket: %s", strerror (errno));
293 exit (1); 303 exit (1);
294 } 304 }
295 size = 1; /* Use size here to avoid making a new variable. */ 305 size = 1; /* Use size here to avoid making a new variable. */
296 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size)); 306 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof (size));
297 size = sizeof (server); 307 size = sizeof (server);
298 memset (&server, 0, size); 308 memset (&server, 0, size);
299 server.sin_family = AF_INET; 309 server.sin_family = AF_INET;
300 server.sin_addr.s_addr = htonl (INADDR_ANY); 310 server.sin_addr.s_addr = htonl (INADDR_ANY);
301 server.sin_port = htons (port); 311 server.sin_port = htons (port);
302 312
303 if (bind (listenfd, (struct sockaddr *)&server, size) == -1) 313 if (bind (listenfd, (struct sockaddr *) &server, size) == -1)
304 { 314 {
305 syslog (LOG_ERR, "bind: %s", strerror (errno)); 315 syslog (LOG_ERR, "bind: %s", strerror (errno));
306 exit (1); 316 exit (1);
...@@ -315,38 +325,37 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port) ...@@ -315,38 +325,37 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port)
315 for (;;) 325 for (;;)
316 { 326 {
317 if (children > maxchildren) 327 if (children > maxchildren)
318 { 328 {
319 syslog (LOG_ERR, _("too many children (%lu)"), 329 syslog (LOG_ERR, _("too many children (%lu)"),
320 (unsigned long) children); 330 (unsigned long) children);
321 pause (); 331 pause ();
322 continue; 332 continue;
323 } 333 }
324 connfd = accept (listenfd, (struct sockaddr *)&client, 334 connfd = accept (listenfd, (struct sockaddr *) &client,
325 (socklen_t*) &size); 335 (socklen_t *) & size);
326 if (connfd == -1) 336 if (connfd == -1)
327 { 337 {
328 if (errno == EINTR) 338 if (errno == EINTR)
329 continue; 339 continue;
330 syslog (LOG_ERR, "accept: %s", strerror (errno)); 340 syslog (LOG_ERR, "accept: %s", strerror (errno));
331 exit (1); 341 exit (1);
332 } 342 }
333 343
334 pid = fork (); 344 pid = fork ();
335 if (pid == -1) 345 if (pid == -1)
336 syslog(LOG_ERR, "fork: %s", strerror (errno)); 346 syslog (LOG_ERR, "fork: %s", strerror (errno));
337 else if (pid == 0) /* Child. */ 347 else if (pid == 0) /* Child. */
338 { 348 {
339 int status; 349 int status;
340 close (listenfd); 350 close (listenfd);
341 status = imap4d_mainloop (connfd, connfd); 351 status = imap4d_mainloop (connfd, connfd);
342 closelog (); 352 closelog ();
343 exit (status); 353 exit (status);
344 } 354 }
345 else 355 else
346 { 356 {
347 ++children; 357 ++children;
348 } 358 }
349 close (connfd); 359 close (connfd);
350 } 360 }
351 } 361 }
352
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 #ifndef _IMAP4D_H 18 #ifndef _IMAP4D_H
19 #define _IMAP4D_H 1 19 #define _IMAP4D_H 1
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
87 #include <mailutils/stream.h> 87 #include <mailutils/stream.h>
88 #include <mailutils/mu_auth.h> 88 #include <mailutils/mu_auth.h>
89 #include <mailutils/url.h> 89 #include <mailutils/url.h>
90 #include <mailutils/tls.h>
90 #include <mailutils/nls.h> 91 #include <mailutils/nls.h>
91 92
92 #ifdef __cplusplus 93 #ifdef __cplusplus
...@@ -126,7 +127,8 @@ struct imap4d_command ...@@ -126,7 +127,8 @@ struct imap4d_command
126 #define ERR_NO_OFILE 2 127 #define ERR_NO_OFILE 2
127 #define ERR_TIMEOUT 3 128 #define ERR_TIMEOUT 3
128 #define ERR_SIGNAL 4 129 #define ERR_SIGNAL 4
129 130 #define ERR_TLS 5
131
130 /* Namespace numbers */ 132 /* Namespace numbers */
131 #define NS_PRIVATE 0 133 #define NS_PRIVATE 0
132 #define NS_OTHER 1 134 #define NS_OTHER 1
...@@ -139,8 +141,6 @@ struct imap4d_command ...@@ -139,8 +141,6 @@ struct imap4d_command
139 #define WCARD_RECURSE_MATCH 2 141 #define WCARD_RECURSE_MATCH 2
140 142
141 extern struct imap4d_command imap4d_command_table[]; 143 extern struct imap4d_command imap4d_command_table[];
142 extern FILE *ifile;
143 extern FILE *ofile;
144 extern mailbox_t mbox; 144 extern mailbox_t mbox;
145 extern char *homedir; 145 extern char *homedir;
146 extern char *rootdir; 146 extern char *rootdir;
...@@ -149,7 +149,12 @@ extern volatile size_t children; ...@@ -149,7 +149,12 @@ extern volatile size_t children;
149 extern int is_virtual; 149 extern int is_virtual;
150 extern struct daemon_param daemon_param; 150 extern struct daemon_param daemon_param;
151 extern struct mu_auth_data *auth_data; 151 extern struct mu_auth_data *auth_data;
152 152
153 #ifdef WITH_TLS
154 extern int tls_available;
155 extern int tls_done;
156 #endif /* WITH_TLS */
157
153 #ifndef HAVE_STRTOK_R 158 #ifndef HAVE_STRTOK_R
154 extern char *strtok_r __P((char *s, const char *delim, char **save_ptr)); 159 extern char *strtok_r __P((char *s, const char *delim, char **save_ptr));
155 #endif 160 #endif
...@@ -181,6 +186,9 @@ extern int imap4d_search0 __P((char *arg, int isuid, char *replybuf, size_t rep ...@@ -181,6 +186,9 @@ extern int imap4d_search0 __P((char *arg, int isuid, char *replybuf, size_t rep
181 extern int imap4d_select __P ((struct imap4d_command *, char *)); 186 extern int imap4d_select __P ((struct imap4d_command *, char *));
182 extern int imap4d_select0 __P ((struct imap4d_command *, char *, int)); 187 extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
183 extern int imap4d_select_status __P((void)); 188 extern int imap4d_select_status __P((void));
189 #ifdef WITH_TLS
190 extern int imap4d_starttls __P ((struct imap4d_command *, char *));
191 #endif /* WITH_TLS */
184 extern int imap4d_status __P ((struct imap4d_command *, char *)); 192 extern int imap4d_status __P ((struct imap4d_command *, char *));
185 extern int imap4d_store __P ((struct imap4d_command *, char *)); 193 extern int imap4d_store __P ((struct imap4d_command *, char *));
186 extern int imap4d_store0 __P ((char *, int, char *, size_t)); 194 extern int imap4d_store0 __P ((char *, int, char *, size_t));
...@@ -220,8 +228,8 @@ extern int util_start __P ((char *)); ...@@ -220,8 +228,8 @@ extern int util_start __P ((char *));
220 extern int util_finish __P ((struct imap4d_command *, int, const char *, ...)); 228 extern int util_finish __P ((struct imap4d_command *, int, const char *, ...));
221 extern int util_getstate __P ((void)); 229 extern int util_getstate __P ((void));
222 extern int util_do_command __P ((char *)); 230 extern int util_do_command __P ((char *));
223 extern char *imap4d_readline __P ((FILE*)); 231 extern char *imap4d_readline __P ((void));
224 extern char *imap4d_readline_ex __P ((FILE*)); 232 extern char *imap4d_readline_ex __P ((void));
225 extern char *util_getword __P ((char *, char **)); 233 extern char *util_getword __P ((char *, char **));
226 extern char *util_getitem __P ((char *, const char *, char **)); 234 extern char *util_getitem __P ((char *, const char *, char **));
227 extern int util_token __P ((char *, size_t, char **)); 235 extern int util_token __P ((char *, size_t, char **));
...@@ -256,7 +264,15 @@ int util_attribute_to_type __P((const char *item, int *type)); ...@@ -256,7 +264,15 @@ int util_attribute_to_type __P((const char *item, int *type));
256 int util_type_to_attribute __P((int type, char **attr_str)); 264 int util_type_to_attribute __P((int type, char **attr_str));
257 int util_attribute_matches_flag __P((attribute_t attr, const char *item)); 265 int util_attribute_matches_flag __P((attribute_t attr, const char *item));
258 int util_uidvalidity __P((mailbox_t smbox, unsigned long *uidvp)); 266 int util_uidvalidity __P((mailbox_t smbox, unsigned long *uidvp));
259 267
268 void util_setio __P((int, int));
269 void util_flush_output __P((void));
270 FILE *util_is_ofile __P((void));
271 #ifdef WITH_TLS
272 int imap4d_init_tls_server __P((void));
273 void imap4d_deinit_tls_server __P((void));
274 #endif /* WITH_TLS */
275
260 #ifdef __cplusplus 276 #ifdef __cplusplus
261 } 277 }
262 #endif 278 #endif
......
...@@ -41,7 +41,7 @@ imap4d_signal (int signo) ...@@ -41,7 +41,7 @@ imap4d_signal (int signo)
41 { 41 {
42 syslog (LOG_CRIT, _("got signal %s"), strsignal (signo)); 42 syslog (LOG_CRIT, _("got signal %s"), strsignal (signo));
43 /* Master process. */ 43 /* Master process. */
44 if (!ofile) 44 if (!(util_is_ofile()))
45 { 45 {
46 syslog (LOG_CRIT, _("MASTER: exiting on signal")); 46 syslog (LOG_CRIT, _("MASTER: exiting on signal"));
47 exit (1); /* abort(); */ 47 exit (1); /* abort(); */
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #include "imap4d.h"
19
20 #ifdef WITH_TLS
21
22 int
23 imap4d_starttls (struct imap4d_command *command, char *arg)
24 {
25 int status;
26 char *sp = NULL;
27
28 if (!tls_available || tls_done)
29 return util_finish (command, RESP_BAD, "Invalid command");
30
31 if (util_getword (arg, &sp))
32 return util_finish (command, RESP_BAD, "Too many args");
33
34 status = util_finish (command, RESP_OK, "Begin TLS negotiation");
35 tls_done = imap4d_init_tls_server ();
36
37 return status;
38 }
39
40 #endif /* WITH_TLS */
41
42 /* EOF */
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 3
4 GNU Mailutils is free software; you can redistribute it and/or modify 4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -13,10 +13,16 @@ ...@@ -13,10 +13,16 @@
13 13
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software 15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
20 static FILE *ifile;
21 static FILE *ofile;
22 #ifdef WITH_TLS
23 static gnutls_session sfile;
24 #endif /* WITH_TLS */
25
20 static int add2set __P ((size_t **, int *, unsigned long)); 26 static int add2set __P ((size_t **, int *, unsigned long));
21 static const char *sc2string __P ((int)); 27 static const char *sc2string __P ((int));
22 28
...@@ -36,7 +42,7 @@ util_getitem (char *s, const char *delim, char **save) ...@@ -36,7 +42,7 @@ util_getitem (char *s, const char *delim, char **save)
36 char *p; 42 char *p;
37 if ((p = s) || (p = *save)) 43 if ((p = s) || (p = *save))
38 { 44 {
39 while (isspace ((unsigned)*p)) 45 while (isspace ((unsigned) *p))
40 p++; 46 p++;
41 if (*p == '"') 47 if (*p == '"')
42 { 48 {
...@@ -45,7 +51,7 @@ util_getitem (char *s, const char *delim, char **save) ...@@ -45,7 +51,7 @@ util_getitem (char *s, const char *delim, char **save)
45 while (*p && *p != '"') 51 while (*p && *p != '"')
46 p++; 52 p++;
47 if (*p == '"') 53 if (*p == '"')
48 p++; 54 p++;
49 *save = (*p) ? p + 1 : p; 55 *save = (*p) ? p + 1 : p;
50 *p = '\0'; 56 *p = '\0';
51 return s; 57 return s;
...@@ -70,23 +76,22 @@ util_token (char *buf, size_t len, char **ptr) ...@@ -70,23 +76,22 @@ util_token (char *buf, size_t len, char **ptr)
70 for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++) 76 for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++)
71 { 77 {
72 if (**ptr == ' ' || **ptr == '.' 78 if (**ptr == ' ' || **ptr == '.'
73 || **ptr == '(' || **ptr == ')' 79 || **ptr == '(' || **ptr == ')'
74 || **ptr == '[' || **ptr == ']' 80 || **ptr == '[' || **ptr == ']'
75 || **ptr == '<' || **ptr == '>' 81 || **ptr == '<' || **ptr == '>' || **ptr == '\r' || **ptr == '\n')
76 || **ptr == '\r' || **ptr == '\n') 82 {
77 { 83 /* Advance. */
78 /* Advance. */ 84 if (start == (*ptr))
79 if (start == (*ptr)) 85 (*ptr)++;
80 (*ptr)++; 86 break;
81 break; 87 }
82 }
83 *buf = **ptr; 88 *buf = **ptr;
84 } 89 }
85 *buf = '\0'; 90 *buf = '\0';
86 /* Skip trailing space. */ 91 /* Skip trailing space. */
87 while (**ptr && **ptr == ' ') 92 while (**ptr && **ptr == ' ')
88 (*ptr)++; 93 (*ptr)++;
89 return *ptr - start; 94 return *ptr - start;
90 } 95 }
91 96
92 /* Remove the surrounding double quotes. */ 97 /* Remove the surrounding double quotes. */
...@@ -100,9 +105,9 @@ util_unquote (char **ptr) ...@@ -100,9 +105,9 @@ util_unquote (char **ptr)
100 { 105 {
101 char *p = ++s; 106 char *p = ++s;
102 while (*p && *p != '"') 107 while (*p && *p != '"')
103 p++; 108 p++;
104 if (*p == '"') 109 if (*p == '"')
105 *p = '\0'; 110 *p = '\0';
106 } 111 }
107 *ptr = s; 112 *ptr = s;
108 } 113 }
...@@ -123,7 +128,8 @@ util_getfullpath (char *name, const char *delim) ...@@ -123,7 +128,8 @@ util_getfullpath (char *name, const char *delim)
123 char *p = util_tilde_expansion (name, delim); 128 char *p = util_tilde_expansion (name, delim);
124 if (*p != delim[0]) 129 if (*p != delim[0])
125 { 130 {
126 char *s = calloc (strlen (homedir) + strlen (delim) + strlen (p) + 1, 1); 131 char *s =
132 calloc (strlen (homedir) + strlen (delim) + strlen (p) + 1, 1);
127 sprintf (s, "%s%s%s", homedir, delim, p); 133 sprintf (s, "%s%s%s", homedir, delim, p);
128 free (p); 134 free (p);
129 p = s; 135 p = s;
...@@ -134,7 +140,7 @@ util_getfullpath (char *name, const char *delim) ...@@ -134,7 +140,7 @@ util_getfullpath (char *name, const char *delim)
134 static int 140 static int
135 comp_int (const void *a, const void *b) 141 comp_int (const void *a, const void *b)
136 { 142 {
137 return *(int*)a - *(int*)b; 143 return *(int *) a - *(int *) b;
138 } 144 }
139 145
140 /* Return in set an allocated array contain (n) numbers, for imap messsage set 146 /* Return in set an allocated array contain (n) numbers, for imap messsage set
...@@ -150,7 +156,7 @@ comp_int (const void *a, const void *b) ...@@ -150,7 +156,7 @@ comp_int (const void *a, const void *b)
150 FIXME: The algo below is to relaxe, things like <,,,> or <:12> or <20:10> 156 FIXME: The algo below is to relaxe, things like <,,,> or <:12> or <20:10>
151 will not generate an error. */ 157 will not generate an error. */
152 int 158 int
153 util_msgset (char *s, size_t **set, int *n, int isuid) 159 util_msgset (char *s, size_t ** set, int *n, int isuid)
154 { 160 {
155 unsigned long val = 0; 161 unsigned long val = 0;
156 unsigned long low = 0; 162 unsigned long low = 0;
...@@ -158,7 +164,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -158,7 +164,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
158 int status = 0; 164 int status = 0;
159 size_t max = 0; 165 size_t max = 0;
160 size_t *tmp; 166 size_t *tmp;
161 int i,j; 167 int i, j;
162 168
163 status = mailbox_messages_count (mbox, &max); 169 status = mailbox_messages_count (mbox, &max);
164 if (status != 0) 170 if (status != 0)
...@@ -178,8 +184,16 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -178,8 +184,16 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
178 switch (*s) 184 switch (*s)
179 { 185 {
180 /* isdigit */ 186 /* isdigit */
181 case '0': case '1': case '2': case '3': case '4': 187 case '0':
182 case '5': case '6': case '7': case '8': case '9': 188 case '1':
189 case '2':
190 case '3':
191 case '4':
192 case '5':
193 case '6':
194 case '7':
195 case '8':
196 case '9':
183 { 197 {
184 errno = 0; 198 errno = 0;
185 val = strtoul (s, &s, 10); 199 val = strtoul (s, &s, 10);
...@@ -206,7 +220,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -206,7 +220,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
206 low = val; 220 low = val;
207 val = tmp; 221 val = tmp;
208 } 222 }
209 for (;low && low <= val; low++) 223 for (; low && low <= val; low++)
210 { 224 {
211 status = add2set (set, n, low); 225 status = add2set (set, n, low);
212 if (status != 0) 226 if (status != 0)
...@@ -227,7 +241,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -227,7 +241,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
227 contiguous set of mesages ranging from the first number to the 241 contiguous set of mesages ranging from the first number to the
228 second: 242 second:
229 3:5 --> 3 4 5 243 3:5 --> 3 4 5
230 */ 244 */
231 case ':': 245 case ':':
232 low = val + 1; 246 low = val + 1;
233 s++; 247 s++;
...@@ -236,7 +250,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -236,7 +250,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
236 /* As a convenience. '*' is provided to refer to the highest message 250 /* As a convenience. '*' is provided to refer to the highest message
237 number int the mailbox: 251 number int the mailbox:
238 5:* --> 5 6 7 8 252 5:* --> 5 6 7 8
239 */ 253 */
240 case '*': 254 case '*':
241 { 255 {
242 val = max; 256 val = max;
...@@ -250,7 +264,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -250,7 +264,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
250 /* IMAP also allows a set of noncontiguous numbers to be specified 264 /* IMAP also allows a set of noncontiguous numbers to be specified
251 with the ',' character: 265 with the ',' character:
252 1,3,5,7 --> 1 3 5 7 266 1,3,5,7 --> 1 3 5 7
253 */ 267 */
254 case ',': 268 case ',':
255 s++; 269 s++;
256 break; 270 break;
...@@ -262,11 +276,11 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -262,11 +276,11 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
262 *n = 0; 276 *n = 0;
263 return EINVAL; 277 return EINVAL;
264 278
265 } /* switch */ 279 } /* switch */
266 280
267 if (done) 281 if (done)
268 break; 282 break;
269 } /* while */ 283 } /* while */
270 284
271 if (low) 285 if (low)
272 { 286 {
...@@ -284,7 +298,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -284,7 +298,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
284 low = val; 298 low = val;
285 val = tmp; 299 val = tmp;
286 } 300 }
287 for (;low && low <= val; low++) 301 for (; low && low <= val; low++)
288 { 302 {
289 status = add2set (set, n, low); 303 status = add2set (set, n, low);
290 if (status != 0) 304 if (status != 0)
...@@ -298,32 +312,49 @@ util_msgset (char *s, size_t **set, int *n, int isuid) ...@@ -298,32 +312,49 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
298 /* Remove duplicates. tmp serves to avoid extra dereferences */ 312 /* Remove duplicates. tmp serves to avoid extra dereferences */
299 tmp = *set; 313 tmp = *set;
300 for (i = 0, j = 1; i < *n; i++) 314 for (i = 0, j = 1; i < *n; i++)
301 if (tmp[j-1] != tmp[i]) 315 if (tmp[j - 1] != tmp[i])
302 tmp[j++] = tmp[i]; 316 tmp[j++] = tmp[i];
303 *n = j; 317 *n = j;
304 return 0; 318 return 0;
305 } 319 }
306 320
307 /* Use vfprintf for the dirty work. */ 321 static int
322 util_send_lowlevel (char *buf)
323 {
324 int status;
325
326 if (buf)
327 {
328 #ifdef WITH_TLS
329 if (tls_done)
330 status = gnutls_record_send (sfile, buf, strlen (buf));
331 else
332 #endif /* WITH_TLS */
333 status = fprintf (ofile, buf);
334 }
335
336 return status;
337 }
338
308 int 339 int
309 util_send (const char *format, ...) 340 util_send (const char *format, ...)
310 { 341 {
311 int status; 342 char *buf = NULL;
343 int status = 0;
312 va_list ap; 344 va_list ap;
345
313 va_start (ap, format); 346 va_start (ap, format);
347 vasprintf (&buf, format, ap);
314 348
315 if (daemon_param.transcript) 349 if (buf)
316 { 350 {
317 char *buf; 351 if (daemon_param.transcript)
318 vasprintf (&buf, format, ap); 352 syslog (LOG_DEBUG, "sent: %s", buf);
319 if (buf) 353
320 { 354 status = util_send_lowlevel (buf);
321 syslog (LOG_DEBUG, "sent: %s", buf); 355 free (buf);
322 free (buf);
323 }
324 } 356 }
325 357
326 status = vfprintf (ofile, format, ap);
327 va_end (ap); 358 va_end (ap);
328 return status; 359 return status;
329 } 360 }
...@@ -361,24 +392,26 @@ util_send_literal (const char *buffer) ...@@ -361,24 +392,26 @@ util_send_literal (const char *buffer)
361 int 392 int
362 util_out (int rc, const char *format, ...) 393 util_out (int rc, const char *format, ...)
363 { 394 {
395 char *tempbuf = NULL;
364 char *buf = NULL; 396 char *buf = NULL;
365 int status; 397 int status = 0;
366 va_list ap; 398 va_list ap;
367 asprintf (&buf, "* %s%s\r\n", sc2string (rc), format); 399
400 asprintf (&tempbuf, "* %s%s\r\n", sc2string (rc), format);
368 va_start (ap, format); 401 va_start (ap, format);
369 if (daemon_param.transcript) 402 vasprintf (&buf, tempbuf, ap);
403
404 if (buf)
370 { 405 {
371 char *buf1 = NULL; 406 if (daemon_param.transcript)
372 vasprintf (&buf1, buf, ap); 407 syslog (LOG_DEBUG, "sent: %s", buf);
373 if (buf1) 408
374 { 409 status = util_send_lowlevel (buf);
375 syslog (LOG_DEBUG, "sent: %s", buf1); 410 free (buf);
376 free (buf1);
377 }
378 } 411 }
379 status = vfprintf (ofile, buf, ap); 412
380 va_end (ap); 413 va_end (ap);
381 free (buf); 414 free (tempbuf);
382 return status; 415 return status;
383 } 416 }
384 417
...@@ -386,29 +419,29 @@ util_out (int rc, const char *format, ...) ...@@ -386,29 +419,29 @@ util_out (int rc, const char *format, ...)
386 int 419 int
387 util_finish (struct imap4d_command *command, int rc, const char *format, ...) 420 util_finish (struct imap4d_command *command, int rc, const char *format, ...)
388 { 421 {
422 char *tempbuf = NULL;
389 char *buf = NULL; 423 char *buf = NULL;
390 int new_state; 424 int new_state;
391 int status; 425 int status = 0;
392 va_list ap; 426 va_list ap;
393 427
394 asprintf (&buf, "%s %s%s %s\r\n", command->tag, sc2string (rc), 428 asprintf (&tempbuf, "%s %s%s %s\r\n", command->tag, sc2string (rc),
395 command->name, format); 429 command->name, format);
396
397 va_start (ap, format); 430 va_start (ap, format);
398 if (daemon_param.transcript) 431 vasprintf (&buf, tempbuf, ap);
432
433 if (buf)
399 { 434 {
400 char *buf1 = NULL; 435 if (daemon_param.transcript)
401 vasprintf (&buf1, buf, ap); 436 syslog (LOG_DEBUG, "sent: %s", buf);
402 if (buf1) 437
403 { 438 status = util_send_lowlevel (buf);
404 syslog (LOG_DEBUG, "sent: %s", buf1); 439 free (buf);
405 free (buf1);
406 }
407 } 440 }
408 441
409 status = vfprintf (ofile, buf, ap);
410 va_end (ap); 442 va_end (ap);
411 free (buf); 443 free (tempbuf);
444
412 /* Reset the state. */ 445 /* Reset the state. */
413 if (rc == RESP_OK) 446 if (rc == RESP_OK)
414 new_state = command->success; 447 new_state = command->success;
...@@ -416,9 +449,10 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) ...@@ -416,9 +449,10 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
416 new_state = command->failure; 449 new_state = command->failure;
417 else 450 else
418 new_state = STATE_NONE; 451 new_state = STATE_NONE;
419 452
420 if (new_state != STATE_NONE) 453 if (new_state != STATE_NONE)
421 state = new_state; 454 state = new_state;
455
422 return status; 456 return status;
423 } 457 }
424 458
...@@ -429,7 +463,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) ...@@ -429,7 +463,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
429 the number of octets, close brace ("}"), and CRLF. 463 the number of octets, close brace ("}"), and CRLF.
430 */ 464 */
431 char * 465 char *
432 imap4d_readline (FILE *fp) 466 imap4d_readline (void)
433 { 467 {
434 char buffer[512]; 468 char buffer[512];
435 size_t len; 469 size_t len;
...@@ -440,13 +474,28 @@ imap4d_readline (FILE *fp) ...@@ -440,13 +474,28 @@ imap4d_readline (FILE *fp)
440 if (!line) 474 if (!line)
441 imap4d_bye (ERR_NO_MEM); 475 imap4d_bye (ERR_NO_MEM);
442 476
443 line[0] = '\0'; /* start with a empty string. */ 477 line[0] = '\0'; /* start with a empty string. */
444 do 478 do
445 { 479 {
446 alarm (daemon_param.timeout); 480 alarm (daemon_param.timeout);
447 if (fgets (buffer, sizeof (buffer), fp) == NULL) 481 #ifdef WITH_TLS
482 if (tls_done)
483 {
484 len = gnutls_record_recv (sfile, buffer, sizeof (buffer) - 1);
485 if (len < 0)
486 {
487 syslog (LOG_INFO, _("TLS error on read: %s"),
488 gnutls_strerror (len));
489 imap4d_bye (ERR_TLS);
490 }
491 else
492 buffer[len] = 0;
493 }
494 else
495 #endif /* WITH_TLS */
496 if (fgets (buffer, sizeof (buffer), ifile) == NULL)
448 { 497 {
449 if (feof (fp)) 498 if (feof (ifile))
450 syslog (LOG_INFO, _("unexpected eof on input")); 499 syslog (LOG_INFO, _("unexpected eof on input"));
451 else if (errno) 500 else if (errno)
452 syslog (LOG_INFO, _("error reading from input file: %m")); 501 syslog (LOG_INFO, _("error reading from input file: %m"));
...@@ -458,9 +507,9 @@ imap4d_readline (FILE *fp) ...@@ -458,9 +507,9 @@ imap4d_readline (FILE *fp)
458 507
459 len = strlen (buffer); 508 len = strlen (buffer);
460 /* If we were in a litteral substract. We have to do it here since the CR 509 /* If we were in a litteral substract. We have to do it here since the CR
461 is part of the count in a literal. */ 510 is part of the count in a literal. */
462 if (number) 511 if (number)
463 number -= len; 512 number -= len;
464 513
465 /* Remove CR. */ 514 /* Remove CR. */
466 if (len > 1 && buffer[len - 1] == '\n') 515 if (len > 1 && buffer[len - 1] == '\n')
...@@ -479,36 +528,37 @@ imap4d_readline (FILE *fp) ...@@ -479,36 +528,37 @@ imap4d_readline (FILE *fp)
479 total = strlen (line); 528 total = strlen (line);
480 529
481 /* I observe some client requesting long FETCH operations since, I did 530 /* I observe some client requesting long FETCH operations since, I did
482 not see any limit in the command length in the RFC, catch things 531 not see any limit in the command length in the RFC, catch things
483 here. */ 532 here. */
484 /* Check that we do have a terminated NL line and we are not retrieving 533 /* Check that we do have a terminated NL line and we are not retrieving
485 a literal. If we don't continue the read. */ 534 a literal. If we don't continue the read. */
486 if (number <= 0 && total && line[total - 1] != '\n') 535 if (number <= 0 && total && line[total - 1] != '\n')
487 continue; 536 continue;
488 537
489 /* Check if the client try to send a literal and make sure we are not 538 /* Check if the client try to send a literal and make sure we are not
490 already retrieving a literal. */ 539 already retrieving a literal. */
491 if (number <= 0 && len > 2) 540 if (number <= 0 && len > 2)
492 { 541 {
493 size_t n = total - 1; /* C arrays are 0-based. */ 542 size_t n = total - 1; /* C arrays are 0-based. */
494 /* A literal is this "{number}\n". The CR is already strip. */ 543 /* A literal is this "{number}\n". The CR is already strip. */
495 if (line[n] == '\n' && line[n - 1] == '}') 544 if (line[n] == '\n' && line[n - 1] == '}')
496 { 545 {
497 /* Search for the matching bracket. */ 546 /* Search for the matching bracket. */
498 while (n && line[n] != '{') n--; 547 while (n && line[n] != '{')
499 if (line [n] == '{') 548 n--;
500 { 549 if (line[n] == '{')
501 char *sp = NULL; 550 {
551 char *sp = NULL;
502 /* Truncate where the literal number was. */ 552 /* Truncate where the literal number was. */
503 line[n] = '\0'; 553 line[n] = '\0';
504 number = strtoul (line + n + 1, &sp, 10); 554 number = strtoul (line + n + 1, &sp, 10);
505 /* Client can ask for non synchronise literal, 555 /* Client can ask for non synchronise literal,
506 if a '+' is append to the octet count. */ 556 if a '+' is append to the octet count. */
507 if (*sp != '+') 557 if (*sp != '+')
508 util_send ("+ GO AHEAD\r\n"); 558 util_send ("+ GO AHEAD\r\n");
509 } 559 }
510 } 560 }
511 } 561 }
512 } 562 }
513 while (number > 0 || (total && line[total - 1] != '\n')); 563 while (number > 0 || (total && line[total - 1] != '\n'));
514 if (daemon_param.transcript) 564 if (daemon_param.transcript)
...@@ -517,16 +567,16 @@ imap4d_readline (FILE *fp) ...@@ -517,16 +567,16 @@ imap4d_readline (FILE *fp)
517 } 567 }
518 568
519 char * 569 char *
520 imap4d_readline_ex (FILE *fp) 570 imap4d_readline_ex (void)
521 { 571 {
522 int len; 572 int len;
523 char *s = imap4d_readline (fp); 573 char *s = imap4d_readline ();
524 574
525 if (s && (len = strlen (s)) > 0 && s[len-1] == '\n') 575 if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n')
526 s[len-1] = 0; 576 s[len - 1] = 0;
527 return s; 577 return s;
528 } 578 }
529 579
530 int 580 int
531 util_do_command (char *prompt) 581 util_do_command (char *prompt)
532 { 582 {
...@@ -540,7 +590,7 @@ util_do_command (char *prompt) ...@@ -540,7 +590,7 @@ util_do_command (char *prompt)
540 if (!tag) 590 if (!tag)
541 { 591 {
542 nullcommand.name = ""; 592 nullcommand.name = "";
543 nullcommand.tag = (char *)"*"; 593 nullcommand.tag = (char *) "*";
544 return util_finish (&nullcommand, RESP_BAD, "Null command"); 594 return util_finish (&nullcommand, RESP_BAD, "Null command");
545 } 595 }
546 else if (!cmd) 596 else if (!cmd)
...@@ -557,16 +607,16 @@ util_do_command (char *prompt) ...@@ -557,16 +607,16 @@ util_do_command (char *prompt)
557 { 607 {
558 nullcommand.name = ""; 608 nullcommand.name = "";
559 nullcommand.tag = tag; 609 nullcommand.tag = tag;
560 return util_finish (&nullcommand, RESP_BAD, "Invalid command"); 610 return util_finish (&nullcommand, RESP_BAD, "Invalid command");
561 } 611 }
562 612
563 command->tag = tag; 613 command->tag = tag;
564 614
565 if (command->states && (command->states & state) == 0) 615 if (command->states && (command->states & state) == 0)
566 return util_finish (command, RESP_BAD, "Wrong state"); 616 return util_finish (command, RESP_BAD, "Wrong state");
567 617
568 len = strlen (sp); 618 len = strlen (sp);
569 if (len && sp[len - 1] == '\n') 619 if (len && sp[len - 1] == '\n')
570 sp[len - 1] = '\0'; 620 sp[len - 1] = '\0';
571 return command->func (command, sp); 621 return command->func (command, sp);
572 } 622 }
...@@ -577,7 +627,7 @@ util_upper (char *s) ...@@ -577,7 +627,7 @@ util_upper (char *s)
577 if (!s) 627 if (!s)
578 return 0; 628 return 0;
579 for (; *s; s++) 629 for (; *s; s++)
580 *s = toupper ((unsigned)*s); 630 *s = toupper ((unsigned) *s);
581 return 0; 631 return 0;
582 } 632 }
583 633
...@@ -585,7 +635,7 @@ util_upper (char *s) ...@@ -585,7 +635,7 @@ util_upper (char *s)
585 int 635 int
586 util_start (char *tag) 636 util_start (char *tag)
587 { 637 {
588 (void)tag; 638 (void) tag;
589 return 0; 639 return 0;
590 } 640 }
591 641
...@@ -632,7 +682,7 @@ sc2string (int rc) ...@@ -632,7 +682,7 @@ sc2string (int rc)
632 } 682 }
633 683
634 static int 684 static int
635 add2set (size_t **set, int *n, unsigned long val) 685 add2set (size_t ** set, int *n, unsigned long val)
636 { 686 {
637 size_t *tmp; 687 size_t *tmp;
638 tmp = realloc (*set, (*n + 1) * sizeof (**set)); 688 tmp = realloc (*set, (*n + 1) * sizeof (**set));
...@@ -650,18 +700,18 @@ add2set (size_t **set, int *n, unsigned long val) ...@@ -650,18 +700,18 @@ add2set (size_t **set, int *n, unsigned long val)
650 } 700 }
651 701
652 int 702 int
653 util_parse_internal_date0 (char *date, time_t *timep, char **endp) 703 util_parse_internal_date0 (char *date, time_t * timep, char **endp)
654 { 704 {
655 struct tm tm; 705 struct tm tm;
656 mu_timezone tz; 706 mu_timezone tz;
657 time_t time; 707 time_t time;
658 char **datep = &date; 708 char **datep = &date;
659 709
660 if (mu_parse_imap_date_time((const char **)datep, &tm, &tz)) 710 if (mu_parse_imap_date_time ((const char **) datep, &tm, &tz))
661 return 1; 711 return 1;
662 712
663 time = mu_tm2time (&tm, &tz); 713 time = mu_tm2time (&tm, &tz);
664 if (time == (time_t) -1) 714 if (time == (time_t) - 1)
665 return 2; 715 return 2;
666 716
667 *timep = time; 717 *timep = time;
...@@ -671,20 +721,20 @@ util_parse_internal_date0 (char *date, time_t *timep, char **endp) ...@@ -671,20 +721,20 @@ util_parse_internal_date0 (char *date, time_t *timep, char **endp)
671 } 721 }
672 722
673 int 723 int
674 util_parse_internal_date (char *date, time_t *timep) 724 util_parse_internal_date (char *date, time_t * timep)
675 { 725 {
676 return util_parse_internal_date0 (date, timep, NULL); 726 return util_parse_internal_date0 (date, timep, NULL);
677 } 727 }
678 728
679 729
680 int 730 int
681 util_parse_822_date (char *date, time_t *timep) 731 util_parse_822_date (char *date, time_t * timep)
682 { 732 {
683 struct tm tm; 733 struct tm tm;
684 mu_timezone tz; 734 mu_timezone tz;
685 const char* p = date; 735 const char *p = date;
686 736
687 if (parse822_date_time(&p, date+strlen(date), &tm, &tz) == 0) 737 if (parse822_date_time (&p, date + strlen (date), &tm, &tz) == 0)
688 { 738 {
689 *timep = mu_tm2time (&tm, &tz); 739 *timep = mu_tm2time (&tm, &tz);
690 return 0; 740 return 0;
...@@ -693,12 +743,12 @@ util_parse_822_date (char *date, time_t *timep) ...@@ -693,12 +743,12 @@ util_parse_822_date (char *date, time_t *timep)
693 } 743 }
694 744
695 int 745 int
696 util_parse_ctime_date (const char *date, time_t *timep) 746 util_parse_ctime_date (const char *date, time_t * timep)
697 { 747 {
698 struct tm tm; 748 struct tm tm;
699 mu_timezone tz; 749 mu_timezone tz;
700 750
701 if (mu_parse_ctime_date_time(&date, &tm, &tz) == 0) 751 if (mu_parse_ctime_date_time (&date, &tm, &tz) == 0)
702 { 752 {
703 *timep = mu_tm2time (&tm, &tz); 753 *timep = mu_tm2time (&tm, &tz);
704 return 0; 754 return 0;
...@@ -711,8 +761,8 @@ util_parse_ctime_date (const char *date, time_t *timep) ...@@ -711,8 +761,8 @@ util_parse_ctime_date (const char *date, time_t *timep)
711 char * 761 char *
712 util_strcasestr (const char *haystack, const char *needle) 762 util_strcasestr (const char *haystack, const char *needle)
713 { 763 {
714 register char *needle_end = strchr(needle, '\0'); 764 register char *needle_end = strchr (needle, '\0');
715 register char *haystack_end = strchr(haystack, '\0'); 765 register char *haystack_end = strchr (haystack, '\0');
716 register size_t needle_len = needle_end - needle; 766 register size_t needle_len = needle_end - needle;
717 register size_t needle_last = needle_len - 1; 767 register size_t needle_last = needle_len - 1;
718 register const char *begin; 768 register const char *begin;
...@@ -729,7 +779,7 @@ util_strcasestr (const char *haystack, const char *needle) ...@@ -729,7 +779,7 @@ util_strcasestr (const char *haystack, const char *needle)
729 register const char *h = begin; 779 register const char *h = begin;
730 780
731 do 781 do
732 if (tolower(*h) != tolower(*n)) 782 if (tolower (*h) != tolower (*n))
733 goto loop; /* continue for loop */ 783 goto loop; /* continue for loop */
734 while (--n >= needle && --h >= haystack); 784 while (--n >= needle && --h >= haystack);
735 785
...@@ -746,14 +796,27 @@ struct ...@@ -746,14 +796,27 @@ struct
746 { 796 {
747 char *name; 797 char *name;
748 int flag; 798 int flag;
749 } _imap4d_attrlist[] = { 799 }
750 { "\\Answered", MU_ATTRIBUTE_ANSWERED }, 800 _imap4d_attrlist[] =
751 { "\\Flagged", MU_ATTRIBUTE_FLAGGED }, 801 {
752 { "\\Deleted", MU_ATTRIBUTE_DELETED }, 802 {
753 { "\\Draft", MU_ATTRIBUTE_DRAFT }, 803 "\\Answered", MU_ATTRIBUTE_ANSWERED}
754 { "\\Seen", MU_ATTRIBUTE_READ }, 804 ,
755 { "\\Recent", MU_ATTRIBUTE_RECENT }, 805 {
756 }; 806 "\\Flagged", MU_ATTRIBUTE_FLAGGED}
807 ,
808 {
809 "\\Deleted", MU_ATTRIBUTE_DELETED}
810 ,
811 {
812 "\\Draft", MU_ATTRIBUTE_DRAFT}
813 ,
814 {
815 "\\Seen", MU_ATTRIBUTE_READ}
816 ,
817 {
818 "\\Recent", MU_ATTRIBUTE_RECENT}
819 ,};
757 820
758 #define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0]) 821 #define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0])
759 822
...@@ -781,8 +844,8 @@ util_type_to_attribute (int type, char **attr_str) ...@@ -781,8 +844,8 @@ util_type_to_attribute (int type, char **attr_str)
781 int i; 844 int i;
782 size_t len = 0; 845 size_t len = 0;
783 846
784 if (MU_ATTRIBUTE_IS_UNSEEN(type)) 847 if (MU_ATTRIBUTE_IS_UNSEEN (type))
785 *attr_str = strdup("\\Recent"); 848 *attr_str = strdup ("\\Recent");
786 else 849 else
787 *attr_str = NULL; 850 *attr_str = NULL;
788 851
...@@ -790,33 +853,33 @@ util_type_to_attribute (int type, char **attr_str) ...@@ -790,33 +853,33 @@ util_type_to_attribute (int type, char **attr_str)
790 if (type & _imap4d_attrlist[i].flag) 853 if (type & _imap4d_attrlist[i].flag)
791 { 854 {
792 attr_list[nattr++] = _imap4d_attrlist[i].name; 855 attr_list[nattr++] = _imap4d_attrlist[i].name;
793 len += 1 + strlen(_imap4d_attrlist[i].name); 856 len += 1 + strlen (_imap4d_attrlist[i].name);
794 } 857 }
795 858
796 *attr_str = malloc(len+1); 859 *attr_str = malloc (len + 1);
797 (*attr_str)[0] = 0; 860 (*attr_str)[0] = 0;
798 if (*attr_str) 861 if (*attr_str)
799 { 862 {
800 for (i = 0; i < nattr; i++) 863 for (i = 0; i < nattr; i++)
801 { 864 {
802 strcat(*attr_str, attr_list[i]); 865 strcat (*attr_str, attr_list[i]);
803 if (i != nattr-1) 866 if (i != nattr - 1)
804 strcat(*attr_str, " "); 867 strcat (*attr_str, " ");
805 } 868 }
806 } 869 }
807 870
808 if (!*attr_str) 871 if (!*attr_str)
809 imap4d_bye (ERR_NO_MEM); 872 imap4d_bye (ERR_NO_MEM);
810 return 0; 873 return 0;
811 } 874 }
812 875
813 void 876 void
814 util_print_flags(attribute_t attr) 877 util_print_flags (attribute_t attr)
815 { 878 {
816 int i; 879 int i;
817 int flags = 0; 880 int flags = 0;
818 int space = 0; 881 int space = 0;
819 882
820 attribute_get_flags (attr, &flags); 883 attribute_get_flags (attr, &flags);
821 for (i = 0; i < _imap4d_nattr; i++) 884 for (i = 0; i < _imap4d_nattr; i++)
822 if (flags & _imap4d_attrlist[i].flag) 885 if (flags & _imap4d_attrlist[i].flag)
...@@ -827,11 +890,11 @@ util_print_flags(attribute_t attr) ...@@ -827,11 +890,11 @@ util_print_flags(attribute_t attr)
827 space = 1; 890 space = 1;
828 util_send (_imap4d_attrlist[i].name); 891 util_send (_imap4d_attrlist[i].name);
829 } 892 }
830 893
831 if (MU_ATTRIBUTE_IS_UNSEEN(flags)) 894 if (MU_ATTRIBUTE_IS_UNSEEN (flags))
832 { 895 {
833 if (space) 896 if (space)
834 util_send (" "); 897 util_send (" ");
835 util_send ("\\Recent"); 898 util_send ("\\Recent");
836 } 899 }
837 } 900 }
...@@ -840,7 +903,7 @@ int ...@@ -840,7 +903,7 @@ int
840 util_attribute_matches_flag (attribute_t attr, const char *item) 903 util_attribute_matches_flag (attribute_t attr, const char *item)
841 { 904 {
842 int flags = 0, mask = 0; 905 int flags = 0, mask = 0;
843 906
844 attribute_get_flags (attr, &flags); 907 attribute_get_flags (attr, &flags);
845 util_attribute_to_type (item, &mask); 908 util_attribute_to_type (item, &mask);
846 if (mask == MU_ATTRIBUTE_RECENT) 909 if (mask == MU_ATTRIBUTE_RECENT)
...@@ -851,7 +914,7 @@ util_attribute_matches_flag (attribute_t attr, const char *item) ...@@ -851,7 +914,7 @@ util_attribute_matches_flag (attribute_t attr, const char *item)
851 914
852 915
853 int 916 int
854 util_parse_attributes(char *items, char **save, int *flags) 917 util_parse_attributes (char *items, char **save, int *flags)
855 { 918 {
856 int rc = 0; 919 int rc = 0;
857 920
...@@ -880,13 +943,13 @@ util_parse_attributes(char *items, char **save, int *flags) ...@@ -880,13 +943,13 @@ util_parse_attributes(char *items, char **save, int *flags)
880 943
881 int 944 int
882 util_base64_encode (const unsigned char *input, size_t input_len, 945 util_base64_encode (const unsigned char *input, size_t input_len,
883 unsigned char **output, size_t *output_len) 946 unsigned char **output, size_t * output_len)
884 { 947 {
885 static char b64tab[] = 948 static char b64tab[] =
886 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 949 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
887 size_t olen = 4 * (input_len + 2) / 3; 950 size_t olen = 4 * (input_len + 2) / 3;
888 unsigned char *out = malloc (olen); 951 unsigned char *out = malloc (olen);
889 952
890 if (!out) 953 if (!out)
891 return 1; 954 return 1;
892 *output = out; 955 *output = out;
...@@ -896,7 +959,7 @@ util_base64_encode (const unsigned char *input, size_t input_len, ...@@ -896,7 +959,7 @@ util_base64_encode (const unsigned char *input, size_t input_len,
896 *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)]; 959 *out++ = b64tab[((input[0] << 4) & 0x30) | (input[1] >> 4)];
897 *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)]; 960 *out++ = b64tab[((input[1] << 2) & 0x3c) | (input[2] >> 6)];
898 *out++ = b64tab[input[2] & 0x3f]; 961 *out++ = b64tab[input[2] & 0x3f];
899 olen -= 4; 962 olen -= 4;
900 input_len -= 3; 963 input_len -= 3;
901 input += 3; 964 input += 3;
902 } 965 }
...@@ -917,17 +980,17 @@ util_base64_encode (const unsigned char *input, size_t input_len, ...@@ -917,17 +980,17 @@ util_base64_encode (const unsigned char *input, size_t input_len,
917 980
918 int 981 int
919 util_base64_decode (const unsigned char *input, size_t input_len, 982 util_base64_decode (const unsigned char *input, size_t input_len,
920 unsigned char **output, size_t *output_len) 983 unsigned char **output, size_t * output_len)
921 { 984 {
922 static int b64val[128] = { 985 static int b64val[128] = {
923 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 986 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
924 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 987 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
925 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 988 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
926 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 989 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
927 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 990 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
928 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 991 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
929 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 992 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
930 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 993 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
931 }; 994 };
932 int olen = input_len; 995 int olen = input_len;
933 unsigned char *out = malloc (olen); 996 unsigned char *out = malloc (olen);
...@@ -940,7 +1003,8 @@ util_base64_decode (const unsigned char *input, size_t input_len, ...@@ -940,7 +1003,8 @@ util_base64_decode (const unsigned char *input, size_t input_len,
940 if (input[0] > 127 || b64val[input[0]] == -1 1003 if (input[0] > 127 || b64val[input[0]] == -1
941 || input[1] > 127 || b64val[input[1]] == -1 1004 || input[1] > 127 || b64val[input[1]] == -1
942 || input[2] > 127 || ((input[2] != '=') && (b64val[input[2]] == -1)) 1005 || input[2] > 127 || ((input[2] != '=') && (b64val[input[2]] == -1))
943 || input[3] > 127 || ((input[3] != '=') && (b64val[input[3]] == -1))) 1006 || input[3] > 127 || ((input[3] != '=')
1007 && (b64val[input[3]] == -1)))
944 return -1; 1008 return -1;
945 *out++ = (b64val[input[0]] << 2) | (b64val[input[1]] >> 4); 1009 *out++ = (b64val[input[0]] << 2) | (b64val[input[1]] >> 4);
946 if (input[2] != '=') 1010 if (input[2] != '=')
...@@ -968,7 +1032,7 @@ util_localname () ...@@ -968,7 +1032,7 @@ util_localname ()
968 int name_len = 256; 1032 int name_len = 256;
969 int status = 1; 1033 int status = 1;
970 struct hostent *hp; 1034 struct hostent *hp;
971 1035
972 name = malloc (name_len); 1036 name = malloc (name_len);
973 while (name 1037 while (name
974 && (status = gethostname (name, name_len)) == 0 1038 && (status = gethostname (name, name_len)) == 0
...@@ -981,19 +1045,19 @@ util_localname () ...@@ -981,19 +1045,19 @@ util_localname ()
981 { 1045 {
982 syslog (LOG_CRIT, _("Can't find out my own hostname")); 1046 syslog (LOG_CRIT, _("Can't find out my own hostname"));
983 exit (1); 1047 exit (1);
984 } 1048 }
985 1049
986 hp = gethostbyname (name); 1050 hp = gethostbyname (name);
987 if (hp) 1051 if (hp)
988 { 1052 {
989 struct in_addr inaddr; 1053 struct in_addr inaddr;
990 inaddr.s_addr = *(unsigned int*)hp->h_addr; 1054 inaddr.s_addr = *(unsigned int *) hp->h_addr;
991 hp = gethostbyaddr ((const char *)&inaddr, 1055 hp = gethostbyaddr ((const char *) &inaddr,
992 sizeof (struct in_addr), AF_INET); 1056 sizeof (struct in_addr), AF_INET);
993 if (hp) 1057 if (hp)
994 { 1058 {
995 free (name); 1059 free (name);
996 name = strdup ((char *)hp->h_name); 1060 name = strdup ((char *) hp->h_name);
997 } 1061 }
998 } 1062 }
999 localname = name; 1063 localname = name;
...@@ -1009,7 +1073,7 @@ util_wcard_match (const char *string, const char *pattern, const char *delim) ...@@ -1009,7 +1073,7 @@ util_wcard_match (const char *string, const char *pattern, const char *delim)
1009 const char *p = pattern, *n = string; 1073 const char *p = pattern, *n = string;
1010 char c; 1074 char c;
1011 1075
1012 for (;(c = *p++) != '\0' && *n; n++) 1076 for (; (c = *p++) != '\0' && *n; n++)
1013 { 1077 {
1014 switch (c) 1078 switch (c)
1015 { 1079 {
...@@ -1071,3 +1135,48 @@ util_uidvalidity (mailbox_t smbox, unsigned long *uidvp) ...@@ -1071,3 +1135,48 @@ util_uidvalidity (mailbox_t smbox, unsigned long *uidvp)
1071 smbox = mbox; 1135 smbox = mbox;
1072 return mailbox_uidvalidity (smbox, uidvp); 1136 return mailbox_uidvalidity (smbox, uidvp);
1073 } 1137 }
1138
1139
1140 void
1141 util_setio (int infile, int outfile)
1142 {
1143 ifile = fdopen (infile, "r");
1144 ofile = fdopen (outfile, "w");
1145 if (!ofile || !ifile)
1146 imap4d_bye (ERR_NO_OFILE);
1147
1148 setvbuf (ofile, NULL, _IOLBF, 0);
1149 }
1150
1151 void
1152 util_flush_output ()
1153 {
1154 if (!tls_done)
1155 fflush (ofile);
1156 }
1157
1158 FILE *
1159 util_is_ofile ()
1160 {
1161 return ofile;
1162 }
1163
1164 #ifdef WITH_TLS
1165
1166 int
1167 imap4d_init_tls_server ()
1168 {
1169 sfile =
1170 (gnutls_session) mu_init_tls_server (fileno (ifile), fileno (ofile));
1171 if (!sfile)
1172 return 0;
1173 return 1;
1174 }
1175
1176 void
1177 imap4d_deinit_tls_server ()
1178 {
1179 mu_deinit_tls_server (sfile);
1180 }
1181
1182 #endif /* WITH_TLS */
......