Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
John McEleney
/
mailutils
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit
6b97e35b
...
6b97e35bebf12ea2a4e2d47a2c056ef53e46bd3d
authored
2003-01-17 19:07:15 +0000
by
Wojciech Polak
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Added TLS/SSL support (via GnuTLS)
1 parent
3311ee56
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
498 additions
and
316 deletions
imap4d/Makefile.am
imap4d/auth_gss.c
imap4d/bye.c
imap4d/capability.c
imap4d/commands.c
imap4d/imap4d.c
imap4d/imap4d.h
imap4d/signal.c
imap4d/starttls.c
imap4d/util.c
imap4d/Makefile.am
View file @
6b97e35
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
## Copyright (C) 1999, 2000, 2001, 2002
, 2003
Free Software Foundation, Inc.
##
## GNU Mail
tu
ils is free software; you can redistribute it and/or
## GNU Mail
ut
ils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2, or (at
## your option) any later version.
##
##
This program
is distributed in the hope that it will be useful, but
##
GNU Mailutils
is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with
this program
; if not, write to the Free Software
## along with
GNU Mailutils
; if not, write to the Free Software
## Foundation, Inc.
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
...
...
@@ -26,8 +26,8 @@ imap4d_LDADD = @AUTHOBJS@ ../mailbox/libmailbox.la @AUTHLIBS@ ../lib/libmailuti
imap4d_SOURCES
=
append.c authenticate.c bye.c capability.c check.c close.c
\
commands.c copy.c create.c delete.c examine.c expunge.c fetch.c imap4d.c
\
imap4d.h list.c logout.c login.c lsub.c namespace.c noop.c rename.c search.c
\
select
.c signal.c sta
tus.c store.c subscribe.c sync.c uid.c unsubscribe
.c
\
util.c version.c
select
.c signal.c sta
rttls.c status.c store.c subscribe.c sync.c uid
.c
\
u
nsubscribe.c u
til.c version.c
## This kludge is necessary to correctly establish imap4d -> AUTHOBJS
## dependency. Think about better approach --gray
...
...
imap4d/auth_gss.c
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,9 +13,10 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* GSSAPI authentication for imap (rfc 1731).
/*
GSSAPI authentication for imap (rfc 1731).
*/
#include "imap4d.h"
...
...
@@ -46,11 +47,8 @@ display_status_1 (char *m, OM_uint32 code, int type)
do
{
maj_stat
=
gss_display_status
(
&
min_stat
,
code
,
type
,
GSS_C_NULL_OID
,
&
msg_ctx
,
&
msg
);
syslog
(
LOG_ERR
,
_
(
"GSS-API error %s: %s
\n
"
),
m
,
(
char
*
)
msg
.
value
);
type
,
GSS_C_NULL_OID
,
&
msg_ctx
,
&
msg
);
syslog
(
LOG_ERR
,
_
(
"GSS-API error %s: %s
\n
"
),
m
,
(
char
*
)
msg
.
value
);
gss_release_buffer
(
&
min_stat
,
&
msg
);
}
while
(
msg_ctx
);
...
...
@@ -64,14 +62,14 @@ display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
}
static
int
imap4d_gss_userok
(
gss_buffer_t
client_name
,
char
*
name
)
imap4d_gss_userok
(
gss_buffer_t
client_name
,
char
*
name
)
{
int
rc
=
-
1
;
krb5_principal
p
;
krb5_context
kcontext
;
krb5_init_context
(
&
kcontext
);
if
(
krb5_parse_name
(
kcontext
,
client_name
->
value
,
&
p
)
!=
0
)
return
-
1
;
if
(
krb5_kuserok
(
kcontext
,
p
,
name
))
...
...
@@ -99,57 +97,54 @@ auth_gssapi (struct imap4d_command *command, char **username)
gss_qop_t
quality
;
gss_name_t
client
;
gss_buffer_desc
client_name
;
/* Obtain server credentials. RFC 1732 states, that
"The server must issue a ready response with no data and pass the
resulting client supplied token to GSS_Accept_sec_context as
input_token, setting acceptor_cred_handle to NULL (for "use default
credentials"), and 0 for input_context_handle (initially)."
"The server must issue a ready response with no data and pass the
resulting client supplied token to GSS_Accept_sec_context as
input_token, setting acceptor_cred_handle to NULL (for "use default
credentials"), and 0 for input_context_handle (initially)."
In MIT implementation, passing NULL as acceptor_cred_handle won't
work (possibly due to a bug in krb5_gss_accept_sec_context()), so
we acquire server credentials explicitly. */
asprintf
((
char
**
)
&
tmp
,
"imap@%s"
,
util_localname
());
asprintf
((
char
**
)
&
tmp
,
"imap@%s"
,
util_localname
());
tokbuf
.
value
=
tmp
;
tokbuf
.
length
=
strlen
(
tokbuf
.
value
)
+
1
;
maj_stat
=
gss_import_name
(
&
min_stat
,
&
tokbuf
,
gss_nt_service_name
,
&
server_name
);
gss_nt_service_name
,
&
server_name
);
if
(
maj_stat
!=
GSS_S_COMPLETE
)
{
display_status
(
"import name"
,
maj_stat
,
min_stat
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication not available"
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication not available"
);
return
1
;
}
maj_stat
=
gss_acquire_cred
(
&
min_stat
,
server_name
,
0
,
GSS_C_NULL_OID_SET
,
GSS_C_ACCEPT
,
&
server_creds
,
NULL
,
NULL
);
gss_release_name
(
&
min_stat2
,
&
server_name
);
gss_release_name
(
&
min_stat2
,
&
server_name
);
if
(
maj_stat
!=
GSS_S_COMPLETE
)
{
display_status
(
"acquire credentials"
,
maj_stat
,
min_stat
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication not available"
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication not available"
);
return
1
;
}
/* Start the dialogue */
util_send
(
"+ GO AHEAD
\r\n
"
);
context
=
GSS_C_NO_CONTEXT
;
for
(;;)
{
token_str
=
imap4d_readline_ex
(
ifile
);
token_str
=
imap4d_readline_ex
();
util_base64_decode
(
token_str
,
strlen
(
token_str
),
&
tmp
,
&
size
);
tokbuf
.
value
=
tmp
;
tokbuf
.
length
=
size
;
free
(
token_str
);
maj_stat
=
gss_accept_sec_context
(
&
min_stat
,
&
context
,
server_creds
,
...
...
@@ -158,9 +153,7 @@ auth_gssapi (struct imap4d_command *command, char **username)
&
client
,
&
mech_type
,
&
outbuf
,
&
cflags
,
NULL
,
&
cred_handle
);
&
cflags
,
NULL
,
&
cred_handle
);
free
(
tmp
);
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
{
...
...
@@ -176,12 +169,11 @@ auth_gssapi (struct imap4d_command *command, char **username)
else
if
(
maj_stat
==
GSS_S_COMPLETE
)
break
;
/* Bail out otherwise */
display_status
(
"accept context"
,
maj_stat
,
min_stat
);
maj_stat
=
gss_delete_sec_context
(
&
min_stat
,
&
context
,
&
outbuf
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication failed"
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication failed"
);
return
1
;
}
...
...
@@ -191,7 +183,7 @@ auth_gssapi (struct imap4d_command *command, char **username)
util_send
(
"+ %*.*s
\r\n
"
,
size
,
size
,
tmp
);
free
(
tmp
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
token_str
=
imap4d_readline_ex
(
ifile
);
token_str
=
imap4d_readline_ex
();
free
(
token_str
);
}
...
...
@@ -205,15 +197,15 @@ auth_gssapi (struct imap4d_command *command, char **username)
util_send
(
"+ %*.*s
\r\n
"
,
size
,
size
,
tmp
);
free
(
tmp
);
token_str
=
imap4d_readline_ex
(
ifile
);
token_str
=
imap4d_readline_ex
();
util_base64_decode
(
token_str
,
strlen
(
token_str
),
(
unsigned
char
**
)
&
tokbuf
.
value
,
&
tokbuf
.
length
);
(
unsigned
char
**
)
&
tokbuf
.
value
,
&
tokbuf
.
length
);
free
(
token_str
);
gss_unwrap
(
&
min_stat
,
context
,
&
tokbuf
,
&
outbuf
,
&
cflags
,
&
quality
);
free
(
tokbuf
.
value
);
sec_level
=
ntohl
(
*
(
OM_uint32
*
)
outbuf
.
value
);
sec_level
=
ntohl
(
*
(
OM_uint32
*
)
outbuf
.
value
);
/* FIXME: parse sec_level and act accordingly to its settings */
mech
=
sec_level
>>
24
;
...
...
@@ -226,25 +218,23 @@ auth_gssapi (struct imap4d_command *command, char **username)
maj_stat
=
gss_delete_sec_context
(
&
min_stat
,
&
context
,
&
outbuf
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication failed: unsupported protection mechanism"
);
"GSSAPI authentication failed: unsupported protection mechanism"
);
return
1
;
}
protection_mech
=
mech
;
client_buffer_size
=
sec_level
&
0x00ffffffff
;
*
username
=
strdup
((
char
*
)
outbuf
.
value
+
4
);
*
username
=
strdup
((
char
*
)
outbuf
.
value
+
4
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
maj_stat
=
gss_display_name
(
&
min_stat
,
client
,
&
client_name
,
&
mech_type
);
maj_stat
=
gss_display_name
(
&
min_stat
,
client
,
&
client_name
,
&
mech_type
);
if
(
maj_stat
!=
GSS_S_COMPLETE
)
{
display_status
(
"get client name"
,
maj_stat
,
min_stat
);
maj_stat
=
gss_delete_sec_context
(
&
min_stat
,
&
context
,
&
outbuf
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
free
(
*
username
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication failed"
);
util_finish
(
command
,
RESP_NO
,
"GSSAPI authentication failed"
);
return
1
;
}
...
...
@@ -270,8 +260,6 @@ auth_gssapi (struct imap4d_command *command, char **username)
gss_release_buffer
(
&
min_stat
,
&
client_name
);
maj_stat
=
gss_delete_sec_context
(
&
min_stat
,
&
context
,
&
outbuf
);
gss_release_buffer
(
&
min_stat
,
&
outbuf
);
util_finish
(
command
,
RESP_OK
,
"GSSAPI authentication successful"
);
util_finish
(
command
,
RESP_OK
,
"GSSAPI authentication successful"
);
return
0
;
}
...
...
imap4d/bye.c
View file @
6b97e35
...
...
@@ -44,7 +44,7 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
break
;
case
ERR_SIGNAL
:
if
(
ofile
)
if
(
util_is_ofile
())
util_out
(
RESP_BYE
,
"Quitting on signal"
);
syslog
(
LOG_ERR
,
_
(
"Quitting on signal"
));
break
;
...
...
@@ -78,6 +78,14 @@ imap4d_bye0 (int reason, struct imap4d_command *command)
if
(
status
==
EXIT_SUCCESS
&&
command
)
util_finish
(
command
,
RESP_OK
,
"Completed"
);
#ifdef WITH_TLS
if
(
tls_done
)
imap4d_deinit_tls_server
();
if
(
tls_available
)
mu_deinit_tls_libs
();
#endif
/* WITH_TLS */
closelog
();
exit
(
status
);
}
...
...
imap4d/capability.c
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001 Free Software Foundation, Inc.
Copyright (C) 1999, 2001
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "imap4d.h"
...
...
@@ -28,13 +28,20 @@ int
imap4d_capability
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
int
i
;
(
void
)
arg
;
(
void
)
arg
;
util_send
(
"* CAPABILITY"
);
for
(
i
=
0
;
capa
[
i
];
i
++
)
util_send
(
" %s"
,
capa
[
i
]);
util_send
(
" %s"
,
capa
[
i
]);
#ifdef WITH_TLS
if
(
tls_available
)
util_send
(
" STARTTLS"
);
#endif
/* WITH_TLS */
imap4d_auth_capability
();
util_send
(
"
\r\n
"
);
util_send
(
"
\r\n
"
);
return
util_finish
(
command
,
RESP_OK
,
"Completed"
);
}
...
...
imap4d/commands.c
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001 Free Software Foundation, Inc.
Copyright (C) 1999, 2001
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "imap4d.h"
...
...
@@ -45,5 +45,8 @@ struct imap4d_command imap4d_command_table [] =
{
"UID"
,
imap4d_uid
,
STATE_SEL
,
STATE_NONE
,
STATE_NONE
,
NULL
},
{
"NAMESPACE"
,
imap4d_namespace
,
STATE_AUTH
|
STATE_SEL
,
STATE_NONE
,
STATE_NONE
,
NULL
},
{
"X-VERSION"
,
imap4d_version
,
STATE_AUTH
|
STATE_SEL
,
STATE_NONE
,
STATE_NONE
,
NULL
},
#ifdef WITH_TLS
{
"STARTTLS"
,
imap4d_starttls
,
STATE_NONAUTH
,
STATE_NONE
,
STATE_NONE
,
NULL
},
#endif
/* WITH_TLS */
{
NULL
,
0
,
0
,
0
,
0
,
NULL
}
};
...
...
imap4d/imap4d.c
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,47 +13,50 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "imap4d.h"
FILE
*
ifile
;
FILE
*
ofile
;
mailbox_t
mbox
;
char
*
homedir
;
int
state
=
STATE_NONAUTH
;
int
debug_mode
=
0
;
struct
mu_auth_data
*
auth_data
;
struct
mu_auth_data
*
auth_data
;
struct
daemon_param
daemon_param
=
{
MODE_INTERACTIVE
,
/* Start in interactive (inetd) mode */
20
,
/* Default maximum number of children */
143
,
/* Standard IMAP4 port */
1800
,
/* RFC2060: 30 minutes. */
0
/* No transcript by default */
MODE_INTERACTIVE
,
/* Start in interactive (inetd) mode */
20
,
/* Default maximum number of children */
143
,
/* Standard IMAP4 port */
1800
,
/* RFC2060: 30 minutes. */
0
/* No transcript by default */
};
#ifdef WITH_TLS
int
tls_available
;
int
tls_done
;
#endif
/* WITH_TLS */
/* Number of child processes. */
volatile
size_t
children
;
const
char
*
argp_program_version
=
"imap4d ("
PACKAGE_STRING
")"
;
static
char
doc
[]
=
N_
(
"GNU imap4d -- the IMAP4D daemon"
);
static
struct
argp_option
options
[]
=
{
static
struct
argp_option
options
[]
=
{
{
"other-namespace"
,
'O'
,
N_
(
"PATHLIST"
),
0
,
N_
(
"set the `other' namespace"
),
0
},
{
"shared-namespace"
,
'S'
,
N_
(
"PATHLIST"
),
0
,
N_
(
"set the `shared' namespace"
),
0
},
{
NULL
,
0
,
NULL
,
0
,
NULL
,
0
}
{
NULL
,
0
,
NULL
,
0
,
NULL
,
0
}
};
static
error_t
imap4d_parse_opt
(
int
key
,
char
*
arg
,
struct
argp_state
*
state
);
static
error_t
imap4d_parse_opt
(
int
key
,
char
*
arg
,
struct
argp_state
*
state
);
static
struct
argp
argp
=
{
options
,
imap4d_parse_opt
,
NULL
,
NULL
,
doc
,
NULL
,
NULL
,
NULL
...
...
@@ -62,6 +65,9 @@ static struct argp argp = {
static
const
char
*
imap4d_capa
[]
=
{
"daemon"
,
"auth"
,
#ifdef WITH_TLS
"tls"
,
#endif
/* WITH_TLS */
"common"
,
"mailbox"
,
"logging"
,
...
...
@@ -69,10 +75,10 @@ static const char *imap4d_capa[] = {
NULL
};
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
void
imap4d_daemon_init
__P
((
void
));
static
void
imap4d_daemon
__P
((
unsigned
int
,
unsigned
int
));
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
void
imap4d_daemon_init
__P
((
void
));
static
void
imap4d_daemon
__P
((
unsigned
int
,
unsigned
int
));
static
int
imap4d_mainloop
__P
((
int
,
int
));
static
error_t
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)
case
ARGP_KEY_INIT
:
state
->
child_inputs
[
0
]
=
state
->
input
;
break
;
case
'O'
:
set_namespace
(
NS_OTHER
,
arg
);
break
;
case
'S'
:
set_namespace
(
NS_SHARED
,
arg
);
break
;
default:
return
ARGP_ERR_UNKNOWN
;
}
...
...
@@ -106,9 +112,12 @@ main (int argc, char **argv)
/* Native Language Support */
mu_init_nls
();
state
=
STATE_NONAUTH
;
/* Starting state in non-auth. */
state
=
STATE_NONAUTH
;
/* Starting state in non-auth. */
MU_AUTH_REGISTER_ALL_MODULES
();
MU_AUTH_REGISTER_ALL_MODULES
();
#ifdef WITH_TLS
mu_tls_init_argp
();
#endif
/* WITH_TLS */
mu_argp_parse
(
&
argp
,
&
argc
,
&
argv
,
0
,
imap4d_capa
,
NULL
,
&
daemon_param
);
#ifdef USE_LIBPAM
...
...
@@ -131,7 +140,7 @@ main (int argc, char **argv)
perror
(
_
(
"Error getting mail group"
));
exit
(
1
);
}
if
(
setgid
(
gr
->
gr_gid
)
==
-
1
)
{
perror
(
_
(
"Error setting mail group"
));
...
...
@@ -143,7 +152,7 @@ main (int argc, char **argv)
{
list_t
bookie
;
registrar_get_list
(
&
bookie
);
list_append
(
bookie
,
mbox_record
);
list_append
(
bookie
,
mbox_record
);
list_append
(
bookie
,
path_record
);
}
...
...
@@ -174,8 +183,15 @@ main (int argc, char **argv)
/* Redirect any stdout error from the library to syslog, they
should not go to the client. */
mu_error_set_print
(
mu_syslog_error_printer
);
umask
(
S_IROTH
|
S_IWOTH
|
S_IXOTH
);
/* 007 */
umask
(
S_IROTH
|
S_IWOTH
|
S_IXOTH
);
/* 007 */
/* Check TLS environment, i.e. cert and key files */
#ifdef WITH_TLS
tls_available
=
mu_check_tls_environment
();
if
(
tls_available
)
tls_available
=
mu_init_tls_libs
();
#endif
/* WITH_TLS */
/* Actually run the daemon. */
if
(
daemon_param
.
mode
==
MODE_DAEMON
)
...
...
@@ -194,18 +210,13 @@ static int
imap4d_mainloop
(
int
infile
,
int
outfile
)
{
char
*
text
;
/* Reset hup to exit. */
signal
(
SIGHUP
,
imap4d_signal
);
/* Timeout alarm. */
signal
(
SIGALRM
,
imap4d_signal
);
ifile
=
fdopen
(
infile
,
"r"
);
ofile
=
fdopen
(
outfile
,
"w"
);
if
(
!
ofile
||
!
ifile
)
imap4d_bye
(
ERR_NO_OFILE
);
setvbuf
(
ofile
,
NULL
,
_IOLBF
,
0
);
util_setio
(
infile
,
outfile
);
/* log information on the connecting client */
if
(
!
debug_mode
)
...
...
@@ -214,11 +225,11 @@ imap4d_mainloop (int infile, int outfile)
int
len
=
sizeof
cs
;
syslog
(
LOG_INFO
,
_
(
"Incoming connection opened"
));
if
(
getpeername
(
infile
,
(
struct
sockaddr
*
)
&
cs
,
&
len
)
<
0
)
if
(
getpeername
(
infile
,
(
struct
sockaddr
*
)
&
cs
,
&
len
)
<
0
)
syslog
(
LOG_ERR
,
_
(
"can't obtain IP address of client: %s"
),
strerror
(
errno
));
else
syslog
(
LOG_INFO
,
_
(
"connect from %s"
),
inet_ntoa
(
cs
.
sin_addr
));
syslog
(
LOG_INFO
,
_
(
"connect from %s"
),
inet_ntoa
(
cs
.
sin_addr
));
text
=
"IMAP4rev1"
;
}
else
...
...
@@ -226,23 +237,22 @@ imap4d_mainloop (int infile, int outfile)
syslog
(
LOG_INFO
,
_
(
"Started in debugging mode"
));
text
=
"IMAP4rev1 Debugging mode"
;
}
/* Greetings. */
util_out
(
RESP_OK
,
text
);
fflush
(
ofile
);
util_flush_output
(
);
while
(
1
)
{
char
*
cmd
=
imap4d_readline
(
ifile
);
char
*
cmd
=
imap4d_readline
();
/* check for updates */
imap4d_sync
();
util_do_command
(
cmd
);
imap4d_sync
();
free
(
cmd
);
fflush
(
ofile
);
util_flush_output
(
);
}
closelog
();
return
EXIT_SUCCESS
;
}
...
...
@@ -256,7 +266,7 @@ imap4d_daemon_init (void)
first three one, in, out, err */
if
(
daemon
(
0
,
0
)
<
0
)
{
perror
(
_
(
"fork failed:"
));
perror
(
_
(
"fork failed:"
));
exit
(
1
);
}
...
...
@@ -289,18 +299,18 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port)
listenfd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
listenfd
==
-
1
)
{
syslog
(
LOG_ERR
,
"socket: %s"
,
strerror
(
errno
));
syslog
(
LOG_ERR
,
"socket: %s"
,
strerror
(
errno
));
exit
(
1
);
}
size
=
1
;
/* Use size here to avoid making a new variable. */
setsockopt
(
listenfd
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
size
,
sizeof
(
size
));
size
=
1
;
/* Use size here to avoid making a new variable. */
setsockopt
(
listenfd
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
size
,
sizeof
(
size
));
size
=
sizeof
(
server
);
memset
(
&
server
,
0
,
size
);
server
.
sin_family
=
AF_INET
;
server
.
sin_addr
.
s_addr
=
htonl
(
INADDR_ANY
);
server
.
sin_port
=
htons
(
port
);
if
(
bind
(
listenfd
,
(
struct
sockaddr
*
)
&
server
,
size
)
==
-
1
)
if
(
bind
(
listenfd
,
(
struct
sockaddr
*
)
&
server
,
size
)
==
-
1
)
{
syslog
(
LOG_ERR
,
"bind: %s"
,
strerror
(
errno
));
exit
(
1
);
...
...
@@ -315,38 +325,37 @@ imap4d_daemon (unsigned int maxchildren, unsigned int port)
for
(;;)
{
if
(
children
>
maxchildren
)
{
syslog
(
LOG_ERR
,
_
(
"too many children (%lu)"
),
{
syslog
(
LOG_ERR
,
_
(
"too many children (%lu)"
),
(
unsigned
long
)
children
);
pause
();
continue
;
}
connfd
=
accept
(
listenfd
,
(
struct
sockaddr
*
)
&
client
,
(
socklen_t
*
)
&
size
);
pause
();
continue
;
}
connfd
=
accept
(
listenfd
,
(
struct
sockaddr
*
)
&
client
,
(
socklen_t
*
)
&
size
);
if
(
connfd
==
-
1
)
{
if
(
errno
==
EINTR
)
continue
;
syslog
(
LOG_ERR
,
"accept: %s"
,
strerror
(
errno
));
exit
(
1
);
}
{
if
(
errno
==
EINTR
)
continue
;
syslog
(
LOG_ERR
,
"accept: %s"
,
strerror
(
errno
));
exit
(
1
);
}
pid
=
fork
();
if
(
pid
==
-
1
)
syslog
(
LOG_ERR
,
"fork: %s"
,
strerror
(
errno
));
else
if
(
pid
==
0
)
/* Child. */
{
int
status
;
close
(
listenfd
);
status
=
imap4d_mainloop
(
connfd
,
connfd
);
closelog
();
exit
(
status
);
}
syslog
(
LOG_ERR
,
"fork: %s"
,
strerror
(
errno
));
else
if
(
pid
==
0
)
/* Child. */
{
int
status
;
close
(
listenfd
);
status
=
imap4d_mainloop
(
connfd
,
connfd
);
closelog
();
exit
(
status
);
}
else
{
++
children
;
}
{
++
children
;
}
close
(
connfd
);
}
}
...
...
imap4d/imap4d.h
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _IMAP4D_H
#define _IMAP4D_H 1
...
...
@@ -87,6 +87,7 @@
#include <mailutils/stream.h>
#include <mailutils/mu_auth.h>
#include <mailutils/url.h>
#include <mailutils/tls.h>
#include <mailutils/nls.h>
#ifdef __cplusplus
...
...
@@ -126,7 +127,8 @@ struct imap4d_command
#define ERR_NO_OFILE 2
#define ERR_TIMEOUT 3
#define ERR_SIGNAL 4
#define ERR_TLS 5
/* Namespace numbers */
#define NS_PRIVATE 0
#define NS_OTHER 1
...
...
@@ -139,8 +141,6 @@ struct imap4d_command
#define WCARD_RECURSE_MATCH 2
extern
struct
imap4d_command
imap4d_command_table
[];
extern
FILE
*
ifile
;
extern
FILE
*
ofile
;
extern
mailbox_t
mbox
;
extern
char
*
homedir
;
extern
char
*
rootdir
;
...
...
@@ -149,7 +149,12 @@ extern volatile size_t children;
extern
int
is_virtual
;
extern
struct
daemon_param
daemon_param
;
extern
struct
mu_auth_data
*
auth_data
;
#ifdef WITH_TLS
extern
int
tls_available
;
extern
int
tls_done
;
#endif
/* WITH_TLS */
#ifndef HAVE_STRTOK_R
extern
char
*
strtok_r
__P
((
char
*
s
,
const
char
*
delim
,
char
**
save_ptr
));
#endif
...
...
@@ -181,6 +186,9 @@ extern int imap4d_search0 __P((char *arg, int isuid, char *replybuf, size_t rep
extern
int
imap4d_select
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_select0
__P
((
struct
imap4d_command
*
,
char
*
,
int
));
extern
int
imap4d_select_status
__P
((
void
));
#ifdef WITH_TLS
extern
int
imap4d_starttls
__P
((
struct
imap4d_command
*
,
char
*
));
#endif
/* WITH_TLS */
extern
int
imap4d_status
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_store
__P
((
struct
imap4d_command
*
,
char
*
));
extern
int
imap4d_store0
__P
((
char
*
,
int
,
char
*
,
size_t
));
...
...
@@ -220,8 +228,8 @@ extern int util_start __P ((char *));
extern
int
util_finish
__P
((
struct
imap4d_command
*
,
int
,
const
char
*
,
...));
extern
int
util_getstate
__P
((
void
));
extern
int
util_do_command
__P
((
char
*
));
extern
char
*
imap4d_readline
__P
((
FILE
*
));
extern
char
*
imap4d_readline_ex
__P
((
FILE
*
));
extern
char
*
imap4d_readline
__P
((
void
));
extern
char
*
imap4d_readline_ex
__P
((
void
));
extern
char
*
util_getword
__P
((
char
*
,
char
**
));
extern
char
*
util_getitem
__P
((
char
*
,
const
char
*
,
char
**
));
extern
int
util_token
__P
((
char
*
,
size_t
,
char
**
));
...
...
@@ -256,7 +264,15 @@ int util_attribute_to_type __P((const char *item, int *type));
int
util_type_to_attribute
__P
((
int
type
,
char
**
attr_str
));
int
util_attribute_matches_flag
__P
((
attribute_t
attr
,
const
char
*
item
));
int
util_uidvalidity
__P
((
mailbox_t
smbox
,
unsigned
long
*
uidvp
));
void
util_setio
__P
((
int
,
int
));
void
util_flush_output
__P
((
void
));
FILE
*
util_is_ofile
__P
((
void
));
#ifdef WITH_TLS
int
imap4d_init_tls_server
__P
((
void
));
void
imap4d_deinit_tls_server
__P
((
void
));
#endif
/* WITH_TLS */
#ifdef __cplusplus
}
#endif
...
...
imap4d/signal.c
View file @
6b97e35
...
...
@@ -41,7 +41,7 @@ imap4d_signal (int signo)
{
syslog
(
LOG_CRIT
,
_
(
"got signal %s"
),
strsignal
(
signo
));
/* Master process. */
if
(
!
ofile
)
if
(
!
(
util_is_ofile
())
)
{
syslog
(
LOG_CRIT
,
_
(
"MASTER: exiting on signal"
));
exit
(
1
);
/* abort(); */
...
...
imap4d/starttls.c
0 → 100644
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "imap4d.h"
#ifdef WITH_TLS
int
imap4d_starttls
(
struct
imap4d_command
*
command
,
char
*
arg
)
{
int
status
;
char
*
sp
=
NULL
;
if
(
!
tls_available
||
tls_done
)
return
util_finish
(
command
,
RESP_BAD
,
"Invalid command"
);
if
(
util_getword
(
arg
,
&
sp
))
return
util_finish
(
command
,
RESP_BAD
,
"Too many args"
);
status
=
util_finish
(
command
,
RESP_OK
,
"Begin TLS negotiation"
);
tls_done
=
imap4d_init_tls_server
();
return
status
;
}
#endif
/* WITH_TLS */
/* EOF */
imap4d/util.c
View file @
6b97e35
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002
, 2003
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -13,10 +13,16 @@
You should have received a copy of the GNU General Public License
along with GNU Mailutils; if not, write to the Free Software
Foundation, Inc.,
675 Mass Ave, Cambridge, MA 02139, USA.
*/
Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "imap4d.h"
static
FILE
*
ifile
;
static
FILE
*
ofile
;
#ifdef WITH_TLS
static
gnutls_session
sfile
;
#endif
/* WITH_TLS */
static
int
add2set
__P
((
size_t
**
,
int
*
,
unsigned
long
));
static
const
char
*
sc2string
__P
((
int
));
...
...
@@ -36,7 +42,7 @@ util_getitem (char *s, const char *delim, char **save)
char
*
p
;
if
((
p
=
s
)
||
(
p
=
*
save
))
{
while
(
isspace
((
unsigned
)
*
p
))
while
(
isspace
((
unsigned
)
*
p
))
p
++
;
if
(
*
p
==
'"'
)
{
...
...
@@ -45,7 +51,7 @@ util_getitem (char *s, const char *delim, char **save)
while
(
*
p
&&
*
p
!=
'"'
)
p
++
;
if
(
*
p
==
'"'
)
p
++
;
p
++
;
*
save
=
(
*
p
)
?
p
+
1
:
p
;
*
p
=
'\0'
;
return
s
;
...
...
@@ -70,23 +76,22 @@ util_token (char *buf, size_t len, char **ptr)
for
(
i
=
1
;
**
ptr
&&
i
<
len
;
(
*
ptr
)
++
,
buf
++
,
i
++
)
{
if
(
**
ptr
==
' '
||
**
ptr
==
'.'
||
**
ptr
==
'('
||
**
ptr
==
')'
||
**
ptr
==
'['
||
**
ptr
==
']'
||
**
ptr
==
'<'
||
**
ptr
==
'>'
||
**
ptr
==
'\r'
||
**
ptr
==
'\n'
)
{
/* Advance. */
if
(
start
==
(
*
ptr
))
(
*
ptr
)
++
;
break
;
}
||
**
ptr
==
'('
||
**
ptr
==
')'
||
**
ptr
==
'['
||
**
ptr
==
']'
||
**
ptr
==
'<'
||
**
ptr
==
'>'
||
**
ptr
==
'\r'
||
**
ptr
==
'\n'
)
{
/* Advance. */
if
(
start
==
(
*
ptr
))
(
*
ptr
)
++
;
break
;
}
*
buf
=
**
ptr
;
}
}
*
buf
=
'\0'
;
/* Skip trailing space. */
while
(
**
ptr
&&
**
ptr
==
' '
)
(
*
ptr
)
++
;
return
*
ptr
-
start
;
return
*
ptr
-
start
;
}
/* Remove the surrounding double quotes. */
...
...
@@ -100,9 +105,9 @@ util_unquote (char **ptr)
{
char
*
p
=
++
s
;
while
(
*
p
&&
*
p
!=
'"'
)
p
++
;
p
++
;
if
(
*
p
==
'"'
)
*
p
=
'\0'
;
*
p
=
'\0'
;
}
*
ptr
=
s
;
}
...
...
@@ -123,7 +128,8 @@ util_getfullpath (char *name, const char *delim)
char
*
p
=
util_tilde_expansion
(
name
,
delim
);
if
(
*
p
!=
delim
[
0
])
{
char
*
s
=
calloc
(
strlen
(
homedir
)
+
strlen
(
delim
)
+
strlen
(
p
)
+
1
,
1
);
char
*
s
=
calloc
(
strlen
(
homedir
)
+
strlen
(
delim
)
+
strlen
(
p
)
+
1
,
1
);
sprintf
(
s
,
"%s%s%s"
,
homedir
,
delim
,
p
);
free
(
p
);
p
=
s
;
...
...
@@ -134,7 +140,7 @@ util_getfullpath (char *name, const char *delim)
static
int
comp_int
(
const
void
*
a
,
const
void
*
b
)
{
return
*
(
int
*
)
a
-
*
(
int
*
)
b
;
return
*
(
int
*
)
a
-
*
(
int
*
)
b
;
}
/* 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)
FIXME: The algo below is to relaxe, things like <,,,> or <:12> or <20:10>
will not generate an error. */
int
util_msgset
(
char
*
s
,
size_t
**
set
,
int
*
n
,
int
isuid
)
util_msgset
(
char
*
s
,
size_t
**
set
,
int
*
n
,
int
isuid
)
{
unsigned
long
val
=
0
;
unsigned
long
low
=
0
;
...
...
@@ -158,7 +164,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
int
status
=
0
;
size_t
max
=
0
;
size_t
*
tmp
;
int
i
,
j
;
int
i
,
j
;
status
=
mailbox_messages_count
(
mbox
,
&
max
);
if
(
status
!=
0
)
...
...
@@ -178,8 +184,16 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
switch
(
*
s
)
{
/* isdigit */
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
case
'0'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
{
errno
=
0
;
val
=
strtoul
(
s
,
&
s
,
10
);
...
...
@@ -206,7 +220,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
low
=
val
;
val
=
tmp
;
}
for
(;
low
&&
low
<=
val
;
low
++
)
for
(;
low
&&
low
<=
val
;
low
++
)
{
status
=
add2set
(
set
,
n
,
low
);
if
(
status
!=
0
)
...
...
@@ -227,7 +241,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
contiguous set of mesages ranging from the first number to the
second:
3:5 --> 3 4 5
*/
*/
case
':'
:
low
=
val
+
1
;
s
++
;
...
...
@@ -236,7 +250,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
/* As a convenience. '*' is provided to refer to the highest message
number int the mailbox:
5:* --> 5 6 7 8
*/
*/
case
'*'
:
{
val
=
max
;
...
...
@@ -250,7 +264,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
/* IMAP also allows a set of noncontiguous numbers to be specified
with the ',' character:
1,3,5,7 --> 1 3 5 7
*/
*/
case
','
:
s
++
;
break
;
...
...
@@ -262,11 +276,11 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
*
n
=
0
;
return
EINVAL
;
}
/* switch */
}
/* switch */
if
(
done
)
break
;
}
/* while */
}
/* while */
if
(
low
)
{
...
...
@@ -284,7 +298,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
low
=
val
;
val
=
tmp
;
}
for
(;
low
&&
low
<=
val
;
low
++
)
for
(;
low
&&
low
<=
val
;
low
++
)
{
status
=
add2set
(
set
,
n
,
low
);
if
(
status
!=
0
)
...
...
@@ -298,32 +312,49 @@ util_msgset (char *s, size_t **set, int *n, int isuid)
/* Remove duplicates. tmp serves to avoid extra dereferences */
tmp
=
*
set
;
for
(
i
=
0
,
j
=
1
;
i
<
*
n
;
i
++
)
if
(
tmp
[
j
-
1
]
!=
tmp
[
i
])
if
(
tmp
[
j
-
1
]
!=
tmp
[
i
])
tmp
[
j
++
]
=
tmp
[
i
];
*
n
=
j
;
return
0
;
}
/* Use vfprintf for the dirty work. */
static
int
util_send_lowlevel
(
char
*
buf
)
{
int
status
;
if
(
buf
)
{
#ifdef WITH_TLS
if
(
tls_done
)
status
=
gnutls_record_send
(
sfile
,
buf
,
strlen
(
buf
));
else
#endif
/* WITH_TLS */
status
=
fprintf
(
ofile
,
buf
);
}
return
status
;
}
int
util_send
(
const
char
*
format
,
...)
{
int
status
;
char
*
buf
=
NULL
;
int
status
=
0
;
va_list
ap
;
va_start
(
ap
,
format
);
vasprintf
(
&
buf
,
format
,
ap
);
if
(
daemon_param
.
transcript
)
if
(
buf
)
{
char
*
buf
;
vasprintf
(
&
buf
,
format
,
ap
);
if
(
buf
)
{
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf
);
free
(
buf
);
}
if
(
daemon_param
.
transcript
)
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf
);
status
=
util_send_lowlevel
(
buf
);
free
(
buf
);
}
status
=
vfprintf
(
ofile
,
format
,
ap
);
va_end
(
ap
);
return
status
;
}
...
...
@@ -361,24 +392,26 @@ util_send_literal (const char *buffer)
int
util_out
(
int
rc
,
const
char
*
format
,
...)
{
char
*
tempbuf
=
NULL
;
char
*
buf
=
NULL
;
int
status
;
int
status
=
0
;
va_list
ap
;
asprintf
(
&
buf
,
"* %s%s
\r\n
"
,
sc2string
(
rc
),
format
);
asprintf
(
&
tempbuf
,
"* %s%s
\r\n
"
,
sc2string
(
rc
),
format
);
va_start
(
ap
,
format
);
if
(
daemon_param
.
transcript
)
vasprintf
(
&
buf
,
tempbuf
,
ap
);
if
(
buf
)
{
char
*
buf1
=
NULL
;
vasprintf
(
&
buf1
,
buf
,
ap
);
if
(
buf1
)
{
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf1
);
free
(
buf1
);
}
if
(
daemon_param
.
transcript
)
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf
);
status
=
util_send_lowlevel
(
buf
);
free
(
buf
);
}
status
=
vfprintf
(
ofile
,
buf
,
ap
);
va_end
(
ap
);
free
(
buf
);
free
(
temp
buf
);
return
status
;
}
...
...
@@ -386,29 +419,29 @@ util_out (int rc, const char *format, ...)
int
util_finish
(
struct
imap4d_command
*
command
,
int
rc
,
const
char
*
format
,
...)
{
char
*
tempbuf
=
NULL
;
char
*
buf
=
NULL
;
int
new_state
;
int
status
;
int
status
=
0
;
va_list
ap
;
asprintf
(
&
buf
,
"%s %s%s %s
\r\n
"
,
command
->
tag
,
sc2string
(
rc
),
asprintf
(
&
temp
buf
,
"%s %s%s %s
\r\n
"
,
command
->
tag
,
sc2string
(
rc
),
command
->
name
,
format
);
va_start
(
ap
,
format
);
if
(
daemon_param
.
transcript
)
vasprintf
(
&
buf
,
tempbuf
,
ap
);
if
(
buf
)
{
char
*
buf1
=
NULL
;
vasprintf
(
&
buf1
,
buf
,
ap
);
if
(
buf1
)
{
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf1
);
free
(
buf1
);
}
if
(
daemon_param
.
transcript
)
syslog
(
LOG_DEBUG
,
"sent: %s"
,
buf
);
status
=
util_send_lowlevel
(
buf
);
free
(
buf
);
}
status
=
vfprintf
(
ofile
,
buf
,
ap
);
va_end
(
ap
);
free
(
buf
);
free
(
tempbuf
);
/* Reset the state. */
if
(
rc
==
RESP_OK
)
new_state
=
command
->
success
;
...
...
@@ -416,9 +449,10 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
new_state
=
command
->
failure
;
else
new_state
=
STATE_NONE
;
if
(
new_state
!=
STATE_NONE
)
state
=
new_state
;
return
status
;
}
...
...
@@ -429,7 +463,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
the number of octets, close brace ("}"), and CRLF.
*/
char
*
imap4d_readline
(
FILE
*
fp
)
imap4d_readline
(
void
)
{
char
buffer
[
512
];
size_t
len
;
...
...
@@ -440,13 +474,28 @@ imap4d_readline (FILE *fp)
if
(
!
line
)
imap4d_bye
(
ERR_NO_MEM
);
line
[
0
]
=
'\0'
;
/* start with a empty string. */
line
[
0
]
=
'\0'
;
/* start with a empty string. */
do
{
alarm
(
daemon_param
.
timeout
);
if
(
fgets
(
buffer
,
sizeof
(
buffer
),
fp
)
==
NULL
)
#ifdef WITH_TLS
if
(
tls_done
)
{
len
=
gnutls_record_recv
(
sfile
,
buffer
,
sizeof
(
buffer
)
-
1
);
if
(
len
<
0
)
{
syslog
(
LOG_INFO
,
_
(
"TLS error on read: %s"
),
gnutls_strerror
(
len
));
imap4d_bye
(
ERR_TLS
);
}
else
buffer
[
len
]
=
0
;
}
else
#endif
/* WITH_TLS */
if
(
fgets
(
buffer
,
sizeof
(
buffer
),
ifile
)
==
NULL
)
{
if
(
feof
(
fp
))
if
(
feof
(
ifile
))
syslog
(
LOG_INFO
,
_
(
"unexpected eof on input"
));
else
if
(
errno
)
syslog
(
LOG_INFO
,
_
(
"error reading from input file: %m"
));
...
...
@@ -458,9 +507,9 @@ imap4d_readline (FILE *fp)
len
=
strlen
(
buffer
);
/* If we were in a litteral substract. We have to do it here since the CR
is part of the count in a literal. */
is part of the count in a literal. */
if
(
number
)
number
-=
len
;
number
-=
len
;
/* Remove CR. */
if
(
len
>
1
&&
buffer
[
len
-
1
]
==
'\n'
)
...
...
@@ -479,36 +528,37 @@ imap4d_readline (FILE *fp)
total
=
strlen
(
line
);
/* I observe some client requesting long FETCH operations since, I did
not see any limit in the command length in the RFC, catch things
here. */
not see any limit in the command length in the RFC, catch things
here. */
/* Check that we do have a terminated NL line and we are not retrieving
a literal. If we don't continue the read. */
a literal. If we don't continue the read. */
if
(
number
<=
0
&&
total
&&
line
[
total
-
1
]
!=
'\n'
)
continue
;
/* Check if the client try to send a literal and make sure we are not
already retrieving a literal. */
already retrieving a literal. */
if
(
number
<=
0
&&
len
>
2
)
{
size_t
n
=
total
-
1
;
/* C arrays are 0-based. */
{
size_t
n
=
total
-
1
;
/* C arrays are 0-based. */
/* A literal is this "{number}\n". The CR is already strip. */
if
(
line
[
n
]
==
'\n'
&&
line
[
n
-
1
]
==
'}'
)
{
if
(
line
[
n
]
==
'\n'
&&
line
[
n
-
1
]
==
'}'
)
{
/* Search for the matching bracket. */
while
(
n
&&
line
[
n
]
!=
'{'
)
n
--
;
if
(
line
[
n
]
==
'{'
)
{
char
*
sp
=
NULL
;
while
(
n
&&
line
[
n
]
!=
'{'
)
n
--
;
if
(
line
[
n
]
==
'{'
)
{
char
*
sp
=
NULL
;
/* Truncate where the literal number was. */
line
[
n
]
=
'\0'
;
number
=
strtoul
(
line
+
n
+
1
,
&
sp
,
10
);
line
[
n
]
=
'\0'
;
number
=
strtoul
(
line
+
n
+
1
,
&
sp
,
10
);
/* Client can ask for non synchronise literal,
if a '+' is append to the octet count. */
if
(
*
sp
!=
'+'
)
util_send
(
"+ GO AHEAD
\r\n
"
);
}
}
}
if a '+' is append to the octet count. */
if
(
*
sp
!=
'+'
)
util_send
(
"+ GO AHEAD
\r\n
"
);
}
}
}
}
while
(
number
>
0
||
(
total
&&
line
[
total
-
1
]
!=
'\n'
));
if
(
daemon_param
.
transcript
)
...
...
@@ -517,16 +567,16 @@ imap4d_readline (FILE *fp)
}
char
*
imap4d_readline_ex
(
FILE
*
fp
)
imap4d_readline_ex
(
void
)
{
int
len
;
char
*
s
=
imap4d_readline
(
fp
);
char
*
s
=
imap4d_readline
();
if
(
s
&&
(
len
=
strlen
(
s
))
>
0
&&
s
[
len
-
1
]
==
'\n'
)
s
[
len
-
1
]
=
0
;
if
(
s
&&
(
len
=
strlen
(
s
))
>
0
&&
s
[
len
-
1
]
==
'\n'
)
s
[
len
-
1
]
=
0
;
return
s
;
}
}
int
util_do_command
(
char
*
prompt
)
{
...
...
@@ -540,7 +590,7 @@ util_do_command (char *prompt)
if
(
!
tag
)
{
nullcommand
.
name
=
""
;
nullcommand
.
tag
=
(
char
*
)
"*"
;
nullcommand
.
tag
=
(
char
*
)
"*"
;
return
util_finish
(
&
nullcommand
,
RESP_BAD
,
"Null command"
);
}
else
if
(
!
cmd
)
...
...
@@ -557,16 +607,16 @@ util_do_command (char *prompt)
{
nullcommand
.
name
=
""
;
nullcommand
.
tag
=
tag
;
return
util_finish
(
&
nullcommand
,
RESP_BAD
,
"Invalid command"
);
return
util_finish
(
&
nullcommand
,
RESP_BAD
,
"Invalid command"
);
}
command
->
tag
=
tag
;
if
(
command
->
states
&&
(
command
->
states
&
state
)
==
0
)
return
util_finish
(
command
,
RESP_BAD
,
"Wrong state"
);
len
=
strlen
(
sp
);
if
(
len
&&
sp
[
len
-
1
]
==
'\n'
)
if
(
len
&&
sp
[
len
-
1
]
==
'\n'
)
sp
[
len
-
1
]
=
'\0'
;
return
command
->
func
(
command
,
sp
);
}
...
...
@@ -577,7 +627,7 @@ util_upper (char *s)
if
(
!
s
)
return
0
;
for
(;
*
s
;
s
++
)
*
s
=
toupper
((
unsigned
)
*
s
);
*
s
=
toupper
((
unsigned
)
*
s
);
return
0
;
}
...
...
@@ -585,7 +635,7 @@ util_upper (char *s)
int
util_start
(
char
*
tag
)
{
(
void
)
tag
;
(
void
)
tag
;
return
0
;
}
...
...
@@ -632,7 +682,7 @@ sc2string (int rc)
}
static
int
add2set
(
size_t
**
set
,
int
*
n
,
unsigned
long
val
)
add2set
(
size_t
**
set
,
int
*
n
,
unsigned
long
val
)
{
size_t
*
tmp
;
tmp
=
realloc
(
*
set
,
(
*
n
+
1
)
*
sizeof
(
**
set
));
...
...
@@ -650,18 +700,18 @@ add2set (size_t **set, int *n, unsigned long val)
}
int
util_parse_internal_date0
(
char
*
date
,
time_t
*
timep
,
char
**
endp
)
util_parse_internal_date0
(
char
*
date
,
time_t
*
timep
,
char
**
endp
)
{
struct
tm
tm
;
mu_timezone
tz
;
time_t
time
;
char
**
datep
=
&
date
;
if
(
mu_parse_imap_date_time
((
const
char
**
)
datep
,
&
tm
,
&
tz
))
if
(
mu_parse_imap_date_time
((
const
char
**
)
datep
,
&
tm
,
&
tz
))
return
1
;
time
=
mu_tm2time
(
&
tm
,
&
tz
);
if
(
time
==
(
time_t
)
-
1
)
if
(
time
==
(
time_t
)
-
1
)
return
2
;
*
timep
=
time
;
...
...
@@ -671,20 +721,20 @@ util_parse_internal_date0 (char *date, time_t *timep, char **endp)
}
int
util_parse_internal_date
(
char
*
date
,
time_t
*
timep
)
util_parse_internal_date
(
char
*
date
,
time_t
*
timep
)
{
return
util_parse_internal_date0
(
date
,
timep
,
NULL
);
}
int
util_parse_822_date
(
char
*
date
,
time_t
*
timep
)
util_parse_822_date
(
char
*
date
,
time_t
*
timep
)
{
struct
tm
tm
;
mu_timezone
tz
;
const
char
*
p
=
date
;
const
char
*
p
=
date
;
if
(
parse822_date_time
(
&
p
,
date
+
strlen
(
date
),
&
tm
,
&
tz
)
==
0
)
if
(
parse822_date_time
(
&
p
,
date
+
strlen
(
date
),
&
tm
,
&
tz
)
==
0
)
{
*
timep
=
mu_tm2time
(
&
tm
,
&
tz
);
return
0
;
...
...
@@ -693,12 +743,12 @@ util_parse_822_date (char *date, time_t *timep)
}
int
util_parse_ctime_date
(
const
char
*
date
,
time_t
*
timep
)
util_parse_ctime_date
(
const
char
*
date
,
time_t
*
timep
)
{
struct
tm
tm
;
mu_timezone
tz
;
if
(
mu_parse_ctime_date_time
(
&
date
,
&
tm
,
&
tz
)
==
0
)
if
(
mu_parse_ctime_date_time
(
&
date
,
&
tm
,
&
tz
)
==
0
)
{
*
timep
=
mu_tm2time
(
&
tm
,
&
tz
);
return
0
;
...
...
@@ -711,8 +761,8 @@ util_parse_ctime_date (const char *date, time_t *timep)
char
*
util_strcasestr
(
const
char
*
haystack
,
const
char
*
needle
)
{
register
char
*
needle_end
=
strchr
(
needle
,
'\0'
);
register
char
*
haystack_end
=
strchr
(
haystack
,
'\0'
);
register
char
*
needle_end
=
strchr
(
needle
,
'\0'
);
register
char
*
haystack_end
=
strchr
(
haystack
,
'\0'
);
register
size_t
needle_len
=
needle_end
-
needle
;
register
size_t
needle_last
=
needle_len
-
1
;
register
const
char
*
begin
;
...
...
@@ -729,7 +779,7 @@ util_strcasestr (const char *haystack, const char *needle)
register
const
char
*
h
=
begin
;
do
if
(
tolower
(
*
h
)
!=
tolower
(
*
n
))
if
(
tolower
(
*
h
)
!=
tolower
(
*
n
))
goto
loop
;
/* continue for loop */
while
(
--
n
>=
needle
&&
--
h
>=
haystack
);
...
...
@@ -746,14 +796,27 @@ struct
{
char
*
name
;
int
flag
;
}
_imap4d_attrlist
[]
=
{
{
"
\\
Answered"
,
MU_ATTRIBUTE_ANSWERED
},
{
"
\\
Flagged"
,
MU_ATTRIBUTE_FLAGGED
},
{
"
\\
Deleted"
,
MU_ATTRIBUTE_DELETED
},
{
"
\\
Draft"
,
MU_ATTRIBUTE_DRAFT
},
{
"
\\
Seen"
,
MU_ATTRIBUTE_READ
},
{
"
\\
Recent"
,
MU_ATTRIBUTE_RECENT
},
};
}
_imap4d_attrlist
[]
=
{
{
"
\\
Answered"
,
MU_ATTRIBUTE_ANSWERED
}
,
{
"
\\
Flagged"
,
MU_ATTRIBUTE_FLAGGED
}
,
{
"
\\
Deleted"
,
MU_ATTRIBUTE_DELETED
}
,
{
"
\\
Draft"
,
MU_ATTRIBUTE_DRAFT
}
,
{
"
\\
Seen"
,
MU_ATTRIBUTE_READ
}
,
{
"
\\
Recent"
,
MU_ATTRIBUTE_RECENT
}
,};
#define NATTR sizeof(_imap4d_attrlist)/sizeof(_imap4d_attrlist[0])
...
...
@@ -781,8 +844,8 @@ util_type_to_attribute (int type, char **attr_str)
int
i
;
size_t
len
=
0
;
if
(
MU_ATTRIBUTE_IS_UNSEEN
(
type
))
*
attr_str
=
strdup
(
"
\\
Recent"
);
if
(
MU_ATTRIBUTE_IS_UNSEEN
(
type
))
*
attr_str
=
strdup
(
"
\\
Recent"
);
else
*
attr_str
=
NULL
;
...
...
@@ -790,33 +853,33 @@ util_type_to_attribute (int type, char **attr_str)
if
(
type
&
_imap4d_attrlist
[
i
].
flag
)
{
attr_list
[
nattr
++
]
=
_imap4d_attrlist
[
i
].
name
;
len
+=
1
+
strlen
(
_imap4d_attrlist
[
i
].
name
);
len
+=
1
+
strlen
(
_imap4d_attrlist
[
i
].
name
);
}
*
attr_str
=
malloc
(
len
+
1
);
*
attr_str
=
malloc
(
len
+
1
);
(
*
attr_str
)[
0
]
=
0
;
if
(
*
attr_str
)
{
for
(
i
=
0
;
i
<
nattr
;
i
++
)
{
strcat
(
*
attr_str
,
attr_list
[
i
]);
if
(
i
!=
nattr
-
1
)
strcat
(
*
attr_str
,
" "
);
strcat
(
*
attr_str
,
attr_list
[
i
]);
if
(
i
!=
nattr
-
1
)
strcat
(
*
attr_str
,
" "
);
}
}
if
(
!*
attr_str
)
imap4d_bye
(
ERR_NO_MEM
);
return
0
;
}
void
util_print_flags
(
attribute_t
attr
)
util_print_flags
(
attribute_t
attr
)
{
int
i
;
int
flags
=
0
;
int
space
=
0
;
attribute_get_flags
(
attr
,
&
flags
);
for
(
i
=
0
;
i
<
_imap4d_nattr
;
i
++
)
if
(
flags
&
_imap4d_attrlist
[
i
].
flag
)
...
...
@@ -827,11 +890,11 @@ util_print_flags(attribute_t attr)
space
=
1
;
util_send
(
_imap4d_attrlist
[
i
].
name
);
}
if
(
MU_ATTRIBUTE_IS_UNSEEN
(
flags
))
if
(
MU_ATTRIBUTE_IS_UNSEEN
(
flags
))
{
if
(
space
)
util_send
(
" "
);
util_send
(
" "
);
util_send
(
"
\\
Recent"
);
}
}
...
...
@@ -840,7 +903,7 @@ int
util_attribute_matches_flag
(
attribute_t
attr
,
const
char
*
item
)
{
int
flags
=
0
,
mask
=
0
;
attribute_get_flags
(
attr
,
&
flags
);
util_attribute_to_type
(
item
,
&
mask
);
if
(
mask
==
MU_ATTRIBUTE_RECENT
)
...
...
@@ -851,7 +914,7 @@ util_attribute_matches_flag (attribute_t attr, const char *item)
int
util_parse_attributes
(
char
*
items
,
char
**
save
,
int
*
flags
)
util_parse_attributes
(
char
*
items
,
char
**
save
,
int
*
flags
)
{
int
rc
=
0
;
...
...
@@ -880,13 +943,13 @@ util_parse_attributes(char *items, char **save, int *flags)
int
util_base64_encode
(
const
unsigned
char
*
input
,
size_t
input_len
,
unsigned
char
**
output
,
size_t
*
output_len
)
unsigned
char
**
output
,
size_t
*
output_len
)
{
static
char
b64tab
[]
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
;
size_t
olen
=
4
*
(
input_len
+
2
)
/
3
;
unsigned
char
*
out
=
malloc
(
olen
);
if
(
!
out
)
return
1
;
*
output
=
out
;
...
...
@@ -896,7 +959,7 @@ util_base64_encode (const unsigned char *input, size_t input_len,
*
out
++
=
b64tab
[((
input
[
0
]
<<
4
)
&
0x30
)
|
(
input
[
1
]
>>
4
)];
*
out
++
=
b64tab
[((
input
[
1
]
<<
2
)
&
0x3c
)
|
(
input
[
2
]
>>
6
)];
*
out
++
=
b64tab
[
input
[
2
]
&
0x3f
];
olen
-=
4
;
olen
-=
4
;
input_len
-=
3
;
input
+=
3
;
}
...
...
@@ -917,17 +980,17 @@ util_base64_encode (const unsigned char *input, size_t input_len,
int
util_base64_decode
(
const
unsigned
char
*
input
,
size_t
input_len
,
unsigned
char
**
output
,
size_t
*
output_len
)
unsigned
char
**
output
,
size_t
*
output_len
)
{
static
int
b64val
[
128
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
62
,
-
1
,
-
1
,
-
1
,
63
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
,
24
,
25
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
26
,
27
,
28
,
29
,
30
,
31
,
32
,
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
62
,
-
1
,
-
1
,
-
1
,
63
,
52
,
53
,
54
,
55
,
56
,
57
,
58
,
59
,
60
,
61
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
,
24
,
25
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
26
,
27
,
28
,
29
,
30
,
31
,
32
,
33
,
34
,
35
,
36
,
37
,
38
,
39
,
40
,
41
,
42
,
43
,
44
,
45
,
46
,
47
,
48
,
49
,
50
,
51
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
};
int
olen
=
input_len
;
unsigned
char
*
out
=
malloc
(
olen
);
...
...
@@ -940,7 +1003,8 @@ util_base64_decode (const unsigned char *input, size_t input_len,
if
(
input
[
0
]
>
127
||
b64val
[
input
[
0
]]
==
-
1
||
input
[
1
]
>
127
||
b64val
[
input
[
1
]]
==
-
1
||
input
[
2
]
>
127
||
((
input
[
2
]
!=
'='
)
&&
(
b64val
[
input
[
2
]]
==
-
1
))
||
input
[
3
]
>
127
||
((
input
[
3
]
!=
'='
)
&&
(
b64val
[
input
[
3
]]
==
-
1
)))
||
input
[
3
]
>
127
||
((
input
[
3
]
!=
'='
)
&&
(
b64val
[
input
[
3
]]
==
-
1
)))
return
-
1
;
*
out
++
=
(
b64val
[
input
[
0
]]
<<
2
)
|
(
b64val
[
input
[
1
]]
>>
4
);
if
(
input
[
2
]
!=
'='
)
...
...
@@ -968,7 +1032,7 @@ util_localname ()
int
name_len
=
256
;
int
status
=
1
;
struct
hostent
*
hp
;
name
=
malloc
(
name_len
);
while
(
name
&&
(
status
=
gethostname
(
name
,
name_len
))
==
0
...
...
@@ -981,19 +1045,19 @@ util_localname ()
{
syslog
(
LOG_CRIT
,
_
(
"Can't find out my own hostname"
));
exit
(
1
);
}
}
hp
=
gethostbyname
(
name
);
if
(
hp
)
{
struct
in_addr
inaddr
;
inaddr
.
s_addr
=
*
(
unsigned
int
*
)
hp
->
h_addr
;
hp
=
gethostbyaddr
((
const
char
*
)
&
inaddr
,
inaddr
.
s_addr
=
*
(
unsigned
int
*
)
hp
->
h_addr
;
hp
=
gethostbyaddr
((
const
char
*
)
&
inaddr
,
sizeof
(
struct
in_addr
),
AF_INET
);
if
(
hp
)
{
free
(
name
);
name
=
strdup
((
char
*
)
hp
->
h_name
);
name
=
strdup
((
char
*
)
hp
->
h_name
);
}
}
localname
=
name
;
...
...
@@ -1009,7 +1073,7 @@ util_wcard_match (const char *string, const char *pattern, const char *delim)
const
char
*
p
=
pattern
,
*
n
=
string
;
char
c
;
for
(;(
c
=
*
p
++
)
!=
'\0'
&&
*
n
;
n
++
)
for
(;
(
c
=
*
p
++
)
!=
'\0'
&&
*
n
;
n
++
)
{
switch
(
c
)
{
...
...
@@ -1071,3 +1135,48 @@ util_uidvalidity (mailbox_t smbox, unsigned long *uidvp)
smbox
=
mbox
;
return
mailbox_uidvalidity
(
smbox
,
uidvp
);
}
void
util_setio
(
int
infile
,
int
outfile
)
{
ifile
=
fdopen
(
infile
,
"r"
);
ofile
=
fdopen
(
outfile
,
"w"
);
if
(
!
ofile
||
!
ifile
)
imap4d_bye
(
ERR_NO_OFILE
);
setvbuf
(
ofile
,
NULL
,
_IOLBF
,
0
);
}
void
util_flush_output
()
{
if
(
!
tls_done
)
fflush
(
ofile
);
}
FILE
*
util_is_ofile
()
{
return
ofile
;
}
#ifdef WITH_TLS
int
imap4d_init_tls_server
()
{
sfile
=
(
gnutls_session
)
mu_init_tls_server
(
fileno
(
ifile
),
fileno
(
ofile
));
if
(
!
sfile
)
return
0
;
return
1
;
}
void
imap4d_deinit_tls_server
()
{
mu_deinit_tls_server
(
sfile
);
}
#endif
/* WITH_TLS */
...
...
Please
register
or
sign in
to post a comment