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
12c30884
...
12c3088414a4e581901e8bb48648c8249b0b5775
authored
2001-05-02 04:45:12 +0000
by
Alain Magloire
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
See ChangeLog
1 parent
4d68dc11
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
565 additions
and
363 deletions
ChangeLog
argp/Makefile.am
configure.in
frm/Makefile.am
imap4d/Makefile.am
imap4d/util.c
include/mailutils/locker.h
lib/Makefile.am
mail/Makefile.am
mailbox/Makefile.am
mailbox/locker.c
mailbox/mbx_pop.c
mailbox/mime.c
pop3d/Makefile.am
pop3d/apop.c
pop3d/capa.c
pop3d/dele.c
pop3d/extra.c
pop3d/list.c
pop3d/pop3d.c
pop3d/pop3d.h
pop3d/quit.c
pop3d/retr.c
pop3d/rset.c
pop3d/signal.c
pop3d/stat.c
pop3d/user.c
ChangeLog
View file @
12c3088
2001-05-02 Alain Magloire
Some of the Makefile.am contain gcc specific options
like -Wall, -pedantic or -ansi remove them.
* configure.in: Check for stdarg and sysconf.
* mailbox/mime.c (_mime_set_content_type): Delayed the
creation of the header-field content-type until the message
is requested via mime_get_message().
* pop3d/lock.: new File to implement the locking.
* pop3d/apop.c: Rearrange the code around the #ifdefs
to be clearrer.
Make sure that when we use strncpy() that the buffer is
null terminated. Added the locking propose by Sergey to apop.
* pop3d/capa.c: Announce we support PIPELINING.
* pop3d/extra.c (pop3d_abquit): Remove ERR_DEAD_SOCK.
Remove the extra fflush(), the call to exit() always
flush the buffers.
(pop3d_readline): Implement PIPELINING.
* pop3d/pop3d.c: Remove the typedef struct sockaddr SA
for more clarity since it is not use that often.
port is not longer a global variable.
children should have the volatile qualification.
2001-04-29 Alain Magloire
* pop3d/extra.c (pop3d_readline): Modify the loop to be able
to support PIPELINING.
* pop3d/capa.c: Advertise that we support PIPELINING.
2001-04-29 Sergey Poznyakoff
Return values of all signal handlers are changed to RETSIGTYPE
and configure.in is modified accordingly. This is more portable.
* configure.in: New Macro AC_TYPE_SIGNAL.
* mailbox/locker.c (locker_lock): while trying to read pid value
from the pidfile passed wrong buffer length to read() call, namely:
read(fd, buf, sizeof (pid_t)).
2001-04-29 Sergey Poznyakoff
I have modified locker.c to implement reference count. The
struct _locker is now:
struct _locker { int fd; int refcnt; char *fname; int flags; };
The refcnt member gets incremented each time locker_lock is called and
decremented each time locker_unlock is called. Actual locking is
performed only if refcnt == 0 on entry to locker_lock. Similarly,
unlocking is performed only when refcnt gets decremented to 0 by
locker_unlock. Also I have added basic support for NFS-secure
locking.
* mailbox/locker.c: Reference count implementation.
2001-04-25 Alain Magloire
* imap4d/store.c: First implementation.
* mailbox/attribute.c (attribute_unse
e
_flags): New function.
* mailbox/attribute.c (attribute_unse
t
_flags): New function.
2001-04-23 Sergey Poznyakoff
* mailbox/mbx_mbox.c (mbx_expunge): It assumes that mbox_get_message()
will place the pointer to message into mum->message member. But
mbox_get_message() relies on 1-based message numbers, whereas `mum'
pointer is obtained using 0-based indexing
:
pointer is obtained using 0-based indexing
.
2001-04-23 Alain Magloire
Sergey Poznyakoff noted: When the user's mailbox ha
zeor size
mmap
fails on Solaris. On GNU/Linux it reuturn NULL buf subsequet munmap
Sergey Poznyakoff noted: When the user's mailbox ha
s zero size,
mmap
fails on Solaris. On GNU/Linux it reuturn NULL buf subseque
n
t munmap
fails.
* mailbox/mapfile_stream.c: To take care of this
will
set
t
he mfs->ptr t
o NULL for len == 0;
* mailbox/mapfile_stream.c: To take care of this
, mfs->ptr is
set
to NULL for len == 0;
*mailbox/mbx_mbox.c (mbox_is_updated): Should I have return 0 (FALSE)
when size change.
...
...
@@ -48,7 +103,7 @@
2001-04-23 Sergey Poznyakoff
It is often convenient to separte log outputs from POP and SMTP
It is often convenient to separ
a
te log outputs from POP and SMTP
servers. --with-log-facility flag which allows to specify to which
log facility the loggin output should be directed.
System administrators often prefere to have more information about
...
...
argp/Makefile.am
View file @
12c3088
...
...
@@ -15,4 +15,3 @@ noinst_HEADERS = argp-fmtstream.h argp-namefrob.h argp.h
libargp_a_LIBADD
=
../lib/libmailutils.a
CFLAGS
=
-Wall -g
...
...
configure.in
View file @
12c3088
...
...
@@ -56,7 +56,7 @@ AC_HEADER_STDC
AC_HEADER_DIRENT
AM_C_PROTOTYPES
AC_CHECK_HEADERS(argp.h errno.h fcntl.h inttypes.h libgen.h limits.h malloc.h \
paths.h shadow.h std
io.h stdlib.h
string.h strings.h sys/file.h syslog.h \
paths.h shadow.h std
arg.h stdio.h stdlib.h
string.h strings.h sys/file.h syslog.h \
unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
...
...
@@ -66,6 +66,7 @@ AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
dnl Check for working functions
...
...
@@ -80,7 +81,7 @@ if test "$ac_cv_func_fnmatch_works" = "no"; then
: LIBOBJS="$LIBOBJS fnmatch.o"
fi
AC_REPLACE_FUNCS(setenv snprintf strtok_r strncasecmp strcasecmp vasprintf)
AC_CHECK_FUNCS(mkstemp sigaction)
AC_CHECK_FUNCS(mkstemp sigaction
sysconf
)
dnl Check for libraries
AC_CHECK_FUNCS(argp_parse)
...
...
frm/Makefile.am
View file @
12c3088
AUTOMAKE_OPTIONS
=
../lib/ansi2knr
CFLAGS
=
-Wall -pedantic -g
INCLUDES
=
-I
$(top_srcdir)
/include -I
$(top_srcdir)
/lib
bin_PROGRAMS
=
frm
...
...
imap4d/Makefile.am
View file @
12c3088
AUTOMAKE_OPTIONS
=
../lib/ansi2knr
INCLUDES
=
-I
$(top_srcdir)
/lib -I
$(top_srcdir)
/include
CFLAGS
=
-Wall -ansi
sbin_PROGRAMS
=
imap4d
...
...
imap4d/util.c
View file @
12c3088
...
...
@@ -18,11 +18,11 @@
#include "imap4d.h"
#include <ctype.h>
static
int
add2set
(
int
**
set
,
int
*
n
,
unsigned
long
val
,
size_t
max
);
static
const
char
*
sc2string
(
int
rc
);
static
int
add2set
__P
((
int
**
,
int
*
,
unsigned
long
,
size_t
)
);
static
const
char
*
sc2string
__P
((
int
)
);
/*
FIXME: Some words are:
between double quotes, between parenthesis
. */
/*
Get the next space/CR/NL separated word, some words are between double
quotes, strtok() can not handle it
. */
char
*
util_getword
(
char
*
s
,
char
**
save
)
{
...
...
@@ -50,6 +50,7 @@ util_getword (char *s, char **save)
return
strtok_r
(
s
,
"
\r\n
"
,
save
);
}
/* Stop a the first char that IMAP4 represent as a special characters. */
int
util_token
(
char
*
buf
,
size_t
len
,
char
**
ptr
)
{
...
...
@@ -142,7 +143,8 @@ util_tilde_expansion (const char *ref, const char *delim)
return
p
;
}
/* Absolute path. */
/* Get the absolute path. */
/* NOTE: Path is allocated and must be free()d by the caller. */
char
*
util_getfullpath
(
char
*
name
,
const
char
*
delim
)
{
...
...
@@ -158,7 +160,6 @@ util_getfullpath (char *name, const char *delim)
}
/* Return in set an allocated array contain (n) numbers, for imap messsage set
set ::= sequence_num / (sequence_num ":" sequence_num) / (set "," set)
sequence_num ::= nz_number / "*"
;; * is the largest number in use. For message
...
...
@@ -182,6 +183,7 @@ util_msgset (char *s, int **set, int *n, int isuid)
status
=
mailbox_messages_count
(
mbox
,
&
max
);
if
(
status
!=
0
)
return
status
;
/* If it is a uid sequence, override max with the UID. */
if
(
isuid
)
{
message_t
msg
=
NULL
;
...
...
@@ -227,11 +229,20 @@ util_msgset (char *s, int **set, int *n, int isuid)
break
;
}
/* A pair of numbers separated by a ':' character indicates a
contiguous set of mesages ranging from the first number to the
second:
3:5 --> 3 4 5
*/
case
':'
:
low
=
val
+
1
;
s
++
;
break
;
/* As a convenience. '*' is provided to refer to the highest message
number int the mailbox:
5:* --> 5 6 7 8
*/
case
'*'
:
{
if
(
status
!=
0
)
...
...
@@ -246,6 +257,10 @@ util_msgset (char *s, int **set, int *n, int isuid)
break
;
}
/* 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
;
...
...
@@ -275,6 +290,7 @@ util_msgset (char *s, int **set, int *n, int isuid)
return
0
;
}
/* Use vfprintf for the dirty work. */
int
util_send
(
const
char
*
format
,
...)
{
...
...
@@ -286,40 +302,42 @@ util_send (const char *format, ...)
return
status
;
}
/* Send an unsolicited response. */
int
util_out
(
int
rc
,
const
char
*
format
,
...)
{
char
*
buf
=
NULL
;
int
status
;
va_list
ap
;
asprintf
(
&
buf
,
"* %s%s
\r\n
"
,
sc2string
(
rc
),
format
);
va_start
(
ap
,
format
);
vasprintf
(
&
buf
,
format
,
ap
);
status
=
vfprintf
(
ofile
,
buf
,
ap
);
va_end
(
ap
);
fprintf
(
ofile
,
"* %s%s
\r\n
"
,
sc2string
(
rc
),
buf
);
free
(
buf
);
return
0
;
return
status
;
}
/* Send the tag response and reset the state. */
int
util_finish
(
struct
imap4d_command
*
command
,
int
rc
,
const
char
*
format
,
...)
{
char
*
buf
=
NULL
;
const
char
*
resp
;
int
new_state
;
int
status
;
va_list
ap
;
asprintf
(
&
buf
,
"%s %s%s %s
\r\n
"
,
command
->
tag
,
sc2string
(
rc
),
command
->
name
,
format
);
va_start
(
ap
,
format
);
vasprintf
(
&
buf
,
format
,
ap
);
status
=
vfprintf
(
ofile
,
buf
,
ap
);
va_end
(
ap
);
resp
=
sc2string
(
rc
);
fprintf
(
ofile
,
"%s %s%s %s
\r\n
"
,
command
->
tag
,
resp
,
command
->
name
,
buf
);
free
(
buf
);
/* Reset the state. */
new_state
=
(
rc
==
RESP_OK
)
?
command
->
success
:
command
->
failure
;
if
(
new_state
!=
STATE_NONE
)
state
=
new_state
;
return
0
;
return
status
;
}
char
*
...
...
@@ -339,29 +357,27 @@ imap4d_readline (int fd)
do
{
if
(
timeout
>
0
)
if
(
timeout
)
{
available
=
select
(
fd
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
if
(
!
available
)
util_quit
(
1
);
/* FIXME: Timeout, send a "* BYE". */
util_quit
(
1
);
}
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
nread
<
1
)
util_quit
(
1
);
/* FIXME: dead socket, need to do something? */
util_quit
(
1
);
buf
[
nread
]
=
'\0'
;
ret
=
realloc
(
ret
,
(
total
+
nread
+
1
)
*
sizeof
(
char
));
if
(
ret
==
NULL
)
util_quit
(
1
);
/* FIXME: ENOMEM, send a "* BYE" to the client. */
util_quit
(
1
);
memcpy
(
ret
+
total
,
buf
,
nread
+
1
);
total
+=
nread
;
/* FIXME: handle literal strings here. */
}
while
(
memchr
(
buf
,
'\n'
,
nread
)
==
NULL
);
/* Nuke CR'\r' */
for
(
nread
=
total
;
nread
>
0
;
nread
--
)
if
(
ret
[
nread
]
==
'\r'
||
ret
[
nread
]
==
'\n'
)
ret
[
nread
]
=
'\0'
;
...
...
include/mailutils/locker.h
View file @
12c3088
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000
, 2001
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
...
...
@@ -35,7 +35,7 @@ extern "C" {
struct
_locker
;
typedef
struct
_locker
*
locker_t
;
extern
int
locker_create
__P
((
locker_t
*
,
char
*
filename
,
extern
int
locker_create
__P
((
locker_t
*
,
c
onst
c
har
*
filename
,
size_t
len
,
int
flags
));
extern
void
locker_destroy
__P
((
locker_t
*
));
...
...
@@ -47,9 +47,11 @@ extern void locker_destroy __P ((locker_t *));
#define MU_LOCKER_FCNTL 2
#define MU_LOCKER_TIME 4
extern
int
locker_lock
__P
((
locker_t
,
int
flag
));
extern
int
locker_touchlock
__P
((
locker_t
));
extern
int
locker_unlock
__P
((
locker_t
));
#define MU_LOCKER_EXPIRE_TIME (5 * 60)
extern
int
locker_lock
__P
((
locker_t
,
int
flag
));
extern
int
locker_touchlock
__P
((
locker_t
));
extern
int
locker_unlock
__P
((
locker_t
));
#ifdef __cplusplus
}
...
...
lib/Makefile.am
View file @
12c3088
...
...
@@ -12,4 +12,3 @@ noinst_HEADERS = argcv.h error.h fnmatch.h getline.h getopt.h md5.h \
libmailutils_a_LIBADD
=
@LIBOBJS@ @ALLOCA@
CFLAGS
=
-Wall -pedantic -g
...
...
mail/Makefile.am
View file @
12c3088
AUTOMAKE_OPTIONS
=
../lib/ansi2knr no-dependencies
CFLAGS
=
-Wall -g
INCLUDES
=
-I
${
top_srcdir
}
/include -I
${
top_srcdir
}
/lib @ARGPINCS@
bin_PROGRAMS
=
mail
...
...
mailbox/Makefile.am
View file @
12c3088
...
...
@@ -4,7 +4,6 @@ AUTOMAKE_OPTIONS = ../lib/ansi2knr
INCLUDES
=
-I
${
top_srcdir
}
/include -I
${
top_srcdir
}
/mailbox/include
\
-I
${
top_srcdir
}
/lib
CFLAGS
=
-Wall -g
SUBDIRS
=
include
...
...
mailbox/locker.c
View file @
12c3088
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000
, 2001
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
...
...
@@ -35,33 +35,30 @@
#include <mailutils/locker.h>
#define LOCKFILE_ATTR 0444
#define LOCK_EXPIRE_TIME (5 * 60)
/* First draft by Brian Edmond. */
struct
_locker
{
int
fd
;
int
refcnt
;
char
*
fname
;
int
flags
;
};
int
locker_create
(
locker_t
*
plocker
,
char
*
filename
,
size_t
len
,
int
flags
)
locker_create
(
locker_t
*
plocker
,
c
onst
c
har
*
filename
,
size_t
len
,
int
flags
)
{
locker_t
l
;
if
(
plocker
==
NULL
)
if
(
plocker
==
NULL
||
filename
==
NULL
||
len
==
0
)
return
EINVAL
;
if
(
filename
==
NULL
||
len
==
0
)
return
EINVAL
;
l
=
malloc
(
sizeof
(
*
l
));
l
=
malloc
(
sizeof
(
*
l
));
if
(
l
==
NULL
)
return
ENOMEM
;
l
->
fname
=
calloc
(
len
+
5
/*strlen(".lock")*/
+
1
,
sizeof
(
char
));
l
->
fname
=
calloc
(
len
+
5
/*strlen(".lock")*/
+
1
,
sizeof
(
*
(
l
->
fname
)
));
if
(
l
->
fname
==
NULL
)
{
free
(
l
);
...
...
@@ -75,6 +72,7 @@ locker_create (locker_t *plocker, char *filename, size_t len, int flags)
else
l
->
flags
=
MU_LOCKER_TIME
;
/* Default is time lock implementation. */
l
->
fd
=
-
1
;
l
->
refcnt
=
0
;
*
plocker
=
l
;
return
0
;
}
...
...
@@ -98,27 +96,41 @@ locker_lock (locker_t lock, int flags)
pid_t
pid
;
int
removed
=
0
;
(
void
)
flags
;
(
void
)
flags
;
/* Ignore for now. */
if
(
lock
==
NULL
)
return
EINVAL
;
/* Is the lock already applied?
FIXME: should we check flags != lock->flags ?? */
if
(
lock
->
fd
!=
-
1
)
{
lock
->
refcnt
++
;
return
0
;
}
/*
Check for lock existance:
if it exists but the process is gone the lock can be removed,
if if the lock is expired and remove it. */
if
((
fd
=
open
(
lock
->
fname
,
O_RDONLY
))
!=
-
1
)
if the lock is expired, remove it. */
fd
=
open
(
lock
->
fname
,
O_RDONLY
);
if
(
fd
!=
-
1
)
{
/* Check to see if this process is still running. */
if
(
lock
->
flags
&
MU_LOCKER_PID
)
{
if
(
read
(
fd
,
buf
,
sizeof
(
pid_t
))
>
0
)
int
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
nread
>
0
)
{
if
((
pid
=
atoi
(
buf
))
>
0
)
buf
[
nread
]
=
'\0'
;
pid
=
strtol
(
buf
,
NULL
,
10
);
if
(
pid
>
0
)
{
/* Process is gone so we try to remove the lock. */
if
(
kill
(
pid
,
0
)
==
-
1
)
if
(
kill
(
pid
,
0
)
==
-
1
)
removed
=
1
;
}
else
removed
=
1
;
/* Corrupted file, remove the lock. */
}
}
/* Check to see if the lock expired. */
...
...
@@ -126,72 +138,95 @@ locker_lock (locker_t lock, int flags)
{
struct
stat
stbuf
;
fstat
(
fd
,
&
stbuf
);
fstat
(
fd
,
&
stbuf
);
/* The lock has expired. */
if
((
time
(
NULL
)
-
stbuf
.
st_mtime
)
>
LOCK
_EXPIRE_TIME
)
if
((
time
(
NULL
)
-
stbuf
.
st_mtime
)
>
MU_LOCKER
_EXPIRE_TIME
)
removed
=
1
;
}
close
(
fd
);
close
(
fd
);
if
(
removed
)
unlink
(
lock
->
fname
);
unlink
(
lock
->
fname
);
}
/* Try to create the lockfile. */
if
((
fd
=
open
(
lock
->
fname
,
O_WRONLY
|
O_CREAT
|
O_EXCL
,
LOCKFILE_ATTR
))
==
-
1
)
fd
=
open
(
lock
->
fname
,
O_WRONLY
|
O_CREAT
|
O_EXCL
,
LOCKFILE_ATTR
);
if
(
fd
==
-
1
)
return
errno
;
else
{
struct
stat
fn_stat
;
struct
stat
fd_stat
;
if
(
lstat
(
lock
->
fname
,
&
fn_stat
)
||
fstat
(
fd
,
&
fd_stat
)
||
fn_stat
.
st_nlink
!=
1
||
fn_stat
.
st_dev
!=
fd_stat
.
st_dev
||
fn_stat
.
st_ino
!=
fd_stat
.
st_ino
||
fn_stat
.
st_uid
!=
fd_stat
.
st_uid
||
fn_stat
.
st_gid
!=
fd_stat
.
st_gid
)
{
close
(
fd
);
unlink
(
lock
->
fname
);
return
EPERM
;
}
}
/* Success. */
sprintf
(
buf
,
"%ld"
,
(
long
)
getpid
());
write
(
fd
,
buf
,
strlen
(
buf
));
sprintf
(
buf
,
"%ld"
,
(
long
)
getpid
());
write
(
fd
,
buf
,
strlen
(
buf
));
/* Try to get a file lock. */
if
(
lock
->
flags
&
MU_LOCKER_FCNTL
)
{
struct
flock
fl
;
memset
(
&
fl
,
0
,
sizeof
(
struct
flock
));
memset
(
&
fl
,
0
,
sizeof
(
struct
flock
));
fl
.
l_type
=
F_WRLCK
;
if
(
fcntl
(
fd
,
F_SETLK
,
&
fl
)
==
-
1
)
if
(
fcntl
(
fd
,
F_SETLK
,
&
fl
)
==
-
1
)
{
int
err
=
errno
;
/* Could not get the file lock. */
close
(
fd
);
unlink
(
lock
->
fname
);
/* Remove the file I created. */
unlink
(
lock
->
fname
);
/* Remove the file I created. */
return
err
;
}
}
lock
->
fd
=
fd
;
lock
->
refcnt
++
;
return
0
;
}
int
locker_touchlock
(
locker_t
lock
)
{
if
(
!
lock
||
!
lock
->
fname
||
(
lock
->
fd
==
-
1
)
)
if
(
!
lock
||
!
lock
->
fname
||
lock
->
fd
==
-
1
)
return
EINVAL
;
return
(
utime
(
lock
->
fname
,
NULL
)
);
return
utime
(
lock
->
fname
,
NULL
);
}
int
locker_unlock
(
locker_t
lock
)
{
if
(
!
lock
||
!
lock
->
fname
||
(
lock
->
fd
==
-
1
)
)
if
(
!
lock
||
!
lock
->
fname
||
lock
->
fd
==
-
1
||
lock
->
refcnt
<=
0
)
return
EINVAL
;
if
(
--
lock
->
refcnt
>
0
)
return
0
;
if
(
lock
->
flags
&
MU_LOCKER_FCNTL
)
{
struct
flock
fl
;
memset
(
&
fl
,
0
,
sizeof
(
struct
flock
));
memset
(
&
fl
,
0
,
sizeof
(
struct
flock
));
fl
.
l_type
=
F_UNLCK
;
/* Unlock failed
? */
if
(
fcntl
(
lock
->
fd
,
F_SETLK
,
&
fl
)
==
-
1
)
/* Unlock failed? */
if
(
fcntl
(
lock
->
fd
,
F_SETLK
,
&
fl
)
==
-
1
)
return
errno
;
}
close
(
lock
->
fd
);
close
(
lock
->
fd
);
lock
->
fd
=
-
1
;
unlink
(
lock
->
fname
);
unlink
(
lock
->
fname
);
return
0
;
}
...
...
mailbox/mbx_pop.c
View file @
12c3088
...
...
@@ -127,7 +127,7 @@ static int pop_write __P ((pop_data_t));
If the POP server supports TOP, we can cleanly fetch the header.
But otherwise we use the clumsy approach. .i.e for the header we read 'til
^\n then discard the rest, for the body we read after ^\n and discard the
beginning. This a waste, Pop was not conceive for this obviously. */
beginning. This
is
a waste, Pop was not conceive for this obviously. */
struct
_pop_message
{
int
inbody
;
...
...
@@ -175,8 +175,8 @@ struct _pop_data
/* Usefull little Macros, since these are very repetitive. */
/* Check if we're busy ? */
/* POP is a one channel dowload protocol, so if someone
is trying to
do another
command while another is running
/* POP is a one channel dow
n
load protocol, so if someone
is trying to
execute a
command while another is running
something is seriously incorrect, So the best course
of action is to close down the connection and start a new one.
For example mime_t only reads part of the message. If a client
...
...
@@ -193,7 +193,7 @@ struct _pop_data
}
if in the while of the readline, one try to get another email. The pop
server will get seriously confused, and the second message will still
be the first one, There is no way to tell POP servers y
e
! stop/abort.
be the first one, There is no way to tell POP servers y
o
! stop/abort.
The approach is to close the stream and reopen again. So every time
we go in to a function our state is preserve by the triplets
mpd->{func,state,id}. The macro CHECK_BUSY checks if we are not
...
...
mailbox/mime.c
View file @
12c3088
...
...
@@ -395,6 +395,10 @@ _mime_set_content_type(mime_t mime)
header_t
hdr
=
NULL
;
size_t
size
;
/* Delayed the creation of the header 'til they create the final message via
mime_get_message() */
if
(
mime
->
hdrs
==
NULL
)
return
0
;
if
(
mime
->
nmtp_parts
>
1
)
{
if
(
mime
->
flags
&
MIME_ADDED_MULTIPART_CT
)
return
0
;
...
...
pop3d/Makefile.am
View file @
12c3088
AUTOMAKE_OPTIONS
=
../lib/ansi2knr
INCLUDES
=
-I
$(srcdir)
-I
$(top_srcdir)
/lib -I
$(top_srcdir)
/include
CFLAGS
=
-Wall -g
sbin_PROGRAMS
=
pop3d
pop3d_SOURCES
=
apop.c auth.c capa.c dele.c extra.c pop3d.c pop3d.h
\
list
.c noop.c quit.c retr.c rset.c stat.c top.c uidl.c user.c signal.c
pop3d_SOURCES
=
apop.c auth.c capa.c dele.c extra.c pop3d.c pop3d.h
\
list.c lock
.c noop.c quit.c retr.c rset.c stat.c top.c uidl.c user.c signal.c
pop3d_LDADD
=
../mailbox/libmailbox.la ../lib/libmailutils.a @AUTHLIBS@
...
...
pop3d/apop.c
View file @
12c3088
...
...
@@ -17,6 +17,24 @@
#include "pop3d.h"
/*
APOP name digest
Arguments:
a string identifying a mailbox and a MD5 digest string
(both required)
Restrictions:
may only be given in the AUTHORIZATION state after the POP3
greeting or after an unsuccessful USER or PASS command
When the POP3 server receives the APOP command, it verifies
the digest provided. If the digest is correct, the POP3
server issues a positive response, and the POP3 session
enters the TRANSACTION state. Otherwise, a negative
response is issued and the POP3 session remains in the
AUTHORIZATION state. */
/* Check if a username exists in APOP password file
returns pointer to password if found, otherwise NULL */
char
*
...
...
@@ -25,16 +43,11 @@ pop3d_apopuser (const char *user)
char
*
password
;
char
buf
[
POP_MAXCMDLEN
];
struct
stat
st
;
#ifdef WITH_BDB2
int
errno
;
DB
*
dbp
;
DBT
key
,
data
;
/* Check the mode, for security reasons. */
#ifdef WITH_BDB2
if
(
stat
(
APOP_PASSFILE
".db"
,
&
st
)
!=
-
1
)
#else
char
*
tmp
;
FILE
*
apop_file
;
if
(
stat
(
APOP_PASSFILE
".passwd"
,
&
st
)
!=
-
1
)
#endif
if
((
st
.
st_mode
&
0777
)
!=
0600
)
...
...
@@ -44,80 +57,91 @@ pop3d_apopuser (const char *user)
}
#ifdef WITH_BDB2
errno
=
db_open
(
APOP_PASSFILE
".db"
,
DB_HASH
,
DB_RDONLY
,
0600
,
NULL
,
NULL
,
&
dbp
);
if
(
errno
!=
0
)
{
syslog
(
LOG_ERR
,
"Unable to open APOP database: %s"
,
strerror
(
errno
));
return
NULL
;
}
{
int
status
;
DB
*
dbp
;
DBT
key
,
data
;
status
=
db_open
(
APOP_PASSFILE
".db"
,
DB_HASH
,
DB_RDONLY
,
0600
,
NULL
,
NULL
,
&
dbp
);
if
(
status
!=
0
)
{
syslog
(
LOG_ERR
,
"Unable to open APOP db: %s"
,
strerror
(
status
));
return
NULL
;
}
memset
(
&
key
,
0
,
sizeof
(
DBT
));
memset
(
&
data
,
0
,
sizeof
(
DBT
));
memset
(
&
key
,
0
,
sizeof
(
DBT
));
memset
(
&
data
,
0
,
sizeof
(
DBT
));
strncpy
(
buf
,
user
,
sizeof
(
buf
));
key
.
data
=
buf
;
key
.
size
=
strlen
(
user
);
errno
=
dbp
->
get
(
dbp
,
NULL
,
&
key
,
&
data
,
0
);
if
(
errno
!=
0
)
{
syslog
(
LOG_ERR
,
"db_get error: %s"
,
strerror
(
errno
));
dbp
->
close
(
dbp
,
0
);
return
NULL
;
}
strncpy
(
buf
,
user
,
sizeof
buf
);
/* strncpy () is lame and does not NULL terminate. */
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
key
.
data
=
buf
;
key
.
size
=
strlen
(
buf
);
status
=
dbp
->
get
(
dbp
,
NULL
,
&
key
,
&
data
,
0
);
if
(
status
!=
0
)
{
syslog
(
LOG_ERR
,
"db_get error: %s"
,
strerror
(
status
));
dbp
->
close
(
dbp
,
0
);
return
NULL
;
}
password
=
malloc
(
sizeof
(
char
)
*
data
.
size
);
if
(
password
==
NULL
)
{
dbp
->
close
(
dbp
,
0
);
return
NULL
;
}
password
=
calloc
(
data
.
size
+
1
,
sizeof
(
*
password
)
);
if
(
password
==
NULL
)
{
dbp
->
close
(
dbp
,
0
);
return
NULL
;
}
sprintf
(
password
,
"%.*s"
,
(
int
)
data
.
size
,
(
char
*
)
data
.
data
);
dbp
->
close
(
dbp
,
0
);
return
password
;
sprintf
(
password
,
"%.*s"
,
(
int
)
data
.
size
,
(
char
*
)
data
.
data
);
dbp
->
close
(
dbp
,
0
);
return
password
;
}
#else
/* !WITH_BDBD2 */
apop_file
=
fopen
(
APOP_PASSFILE
".passwd"
,
"r"
);
if
(
apop_file
==
NULL
)
{
syslog
(
LOG_INFO
,
"Unable to open APOP password file"
);
return
NULL
;
}
{
char
*
tmp
;
FILE
*
apop_file
;
apop_file
=
fopen
(
APOP_PASSFILE
".passwd"
,
"r"
);
if
(
apop_file
==
NULL
)
{
syslog
(
LOG_INFO
,
"Unable to open APOP password file"
);
return
NULL
;
}
password
=
malloc
(
sizeof
(
char
)
*
APOP_DIGEST
);
if
(
password
==
NULL
)
{
fclose
(
apop_file
);
pop3d_abquit
(
ERR_NO_MEM
);
}
password
[
0
]
=
'\0'
;
password
=
calloc
(
APOP_DIGEST
,
sizeof
(
*
password
));
if
(
password
==
NULL
)
{
fclose
(
apop_file
);
pop3d_abquit
(
ERR_NO_MEM
);
}
while
(
fgets
(
buf
,
sizeof
(
buf
)
-
1
,
apop_file
)
!=
NULL
)
{
tmp
=
strchr
(
buf
,
':'
);
if
(
tmp
==
NULL
)
continue
;
*
tmp
=
'\0'
;
tmp
++
;
if
(
strncmp
(
user
,
buf
,
strlen
(
user
)))
continue
;
strncpy
(
password
,
tmp
,
strlen
(
tmp
));
tmp
=
strchr
(
password
,
'\n'
);
if
(
tmp
)
*
tmp
=
'\0'
;
break
;
}
while
(
fgets
(
buf
,
sizeof
(
buf
)
-
1
,
apop_file
)
!=
NULL
)
{
tmp
=
strchr
(
buf
,
':'
);
if
(
tmp
==
NULL
)
continue
;
*
tmp
++
=
'\0'
;
fclose
(
apop_file
);
if
(
strlen
(
password
)
==
0
)
{
free
(
password
);
return
NULL
;
}
if
(
strncmp
(
user
,
buf
,
strlen
(
user
)))
continue
;
return
password
;
strncpy
(
password
,
tmp
,
APOP_DIGEST
);
/* strncpy () is lame and does not NULL terminate. */
password
[
APOP_DIGEST
-
1
]
=
'\0'
;
tmp
=
strchr
(
password
,
'\n'
);
if
(
tmp
)
*
tmp
=
'\0'
;
break
;
}
fclose
(
apop_file
);
if
(
*
password
==
'\0'
)
{
free
(
password
);
return
NULL
;
}
return
password
;
}
#endif
/* WITH_BDB2 */
}
...
...
@@ -129,8 +153,8 @@ pop3d_apop (const char *arg)
char
buf
[
POP_MAXCMDLEN
];
struct
md5_ctx
md5context
;
unsigned
char
md5digest
[
16
];
int
i
;
int
status
;
int
lockit
=
1
;
if
(
state
!=
AUTHORIZATION
)
return
ERR_WRONG_STATE
;
...
...
@@ -142,6 +166,7 @@ pop3d_apop (const char *arg)
if
(
strlen
(
username
)
>
(
POP_MAXCMDLEN
-
APOP_DIGEST
))
{
free
(
username
);
username
=
NULL
;
return
ERR_BAD_ARGS
;
}
user_digest
=
pop3d_args
(
arg
);
...
...
@@ -150,6 +175,7 @@ pop3d_apop (const char *arg)
if
(
password
==
NULL
)
{
free
(
username
);
username
=
NULL
;
free
(
user_digest
);
return
ERR_BAD_LOGIN
;
}
...
...
@@ -160,15 +186,19 @@ pop3d_apop (const char *arg)
free
(
password
);
md5_finish_ctx
(
&
md5context
,
md5digest
);
tmp
=
buf
;
for
(
i
=
0
;
i
<
16
;
i
++
,
tmp
+=
2
)
sprintf
(
tmp
,
"%02x"
,
md5digest
[
i
]);
{
int
i
;
tmp
=
buf
;
for
(
i
=
0
;
i
<
16
;
i
++
,
tmp
+=
2
)
sprintf
(
tmp
,
"%02x"
,
md5digest
[
i
]);
}
*
tmp
++
=
'\0'
;
if
(
strcmp
(
user_digest
,
buf
))
{
free
(
username
);
username
=
NULL
;
free
(
user_digest
);
return
ERR_BAD_LOGIN
;
}
...
...
@@ -178,24 +208,20 @@ pop3d_apop (const char *arg)
if
(
pw
==
NULL
)
{
free
(
username
);
username
=
NULL
;
return
ERR_BAD_LOGIN
;
}
/* Reset the uid. */
/* FIXME: How about the gid. */
if
(
setuid
(
pw
->
pw_uid
)
==
-
1
)
{
free
(
username
);
username
=
NULL
;
return
ERR_BAD_LOGIN
;
}
if
(
mailbox_create_default
(
&
mbox
,
username
)
!=
0
)
{
free
(
username
);
state
=
AUTHORIZATION
;
return
ERR_UNKNOWN
;
}
else
if
((
status
=
mailbox_open
(
mbox
,
MU_STREAM_RDWR
))
!=
0
)
if
((
status
=
mailbox_create_default
(
&
mbox
,
username
))
!=
0
||
(
status
=
mailbox_open
(
mbox
,
MU_STREAM_RDWR
))
!=
0
)
{
mailbox_destroy
(
&
mbox
);
/* For non existent mailbox, we fake. */
...
...
@@ -205,6 +231,7 @@ pop3d_apop (const char *arg)
||
mailbox_open
(
mbox
,
MU_STREAM_READ
)
!=
0
)
{
free
(
username
);
username
=
NULL
;
state
=
AUTHORIZATION
;
return
ERR_UNKNOWN
;
}
...
...
@@ -212,9 +239,21 @@ pop3d_apop (const char *arg)
else
{
free
(
username
);
username
=
NULL
;
state
=
AUTHORIZATION
;
return
ERR_MBOX_LOCK
;
}
lockit
=
0
;
/* Do not attempt to lock /dev/null ! */
}
if
(
lockit
&&
pop3d_lock
())
{
mailbox_close
(
mbox
);
mailbox_destroy
(
&
mbox
);
state
=
AUTHORIZATION
;
free
(
username
);
username
=
NULL
;
return
ERR_MBOX_LOCK
;
}
state
=
TRANSACTION
;
...
...
pop3d/capa.c
View file @
12c3088
...
...
@@ -17,6 +17,15 @@
#include "pop3d.h"
/*
The CAPA Command
The POP3 CAPA command returns a list of capabilities supported by the
POP3 server. It is available in both the AUTHORIZATION and
TRANSACTION states.
Capabilities available in the AUTHORIZATION state MUST be announced
in both states. */
int
pop3d_capa
(
const
char
*
arg
)
{
...
...
@@ -31,6 +40,10 @@ pop3d_capa (const char *arg)
fprintf
(
ofile
,
"USER
\r\n
"
);
fprintf
(
ofile
,
"UIDL
\r\n
"
);
fprintf
(
ofile
,
"RESP-CODES
\r\n
"
);
fprintf
(
ofile
,
"PIPELINING
\r\n
"
);
/* FIXME: This can be Implemented by setting an header field on the
message. */
/*fprintf (ofile, "EXPIRE NEVER\r\n"); */
if
(
state
==
TRANSACTION
)
/* let's not advertise to just anyone */
fprintf
(
ofile
,
"IMPLEMENTATION %s %s
\r\n
"
,
IMPL
,
VERSION
);
fprintf
(
ofile
,
".
\r\n
"
);
...
...
pop3d/dele.c
View file @
12c3088
...
...
@@ -22,9 +22,9 @@
int
pop3d_dele
(
const
char
*
arg
)
{
size_t
num
=
0
;
size_t
num
;
message_t
msg
;
attribute_t
attr
;
attribute_t
attr
=
NULL
;
if
((
arg
==
NULL
)
||
(
strchr
(
arg
,
' '
)
!=
NULL
))
return
ERR_BAD_ARGS
;
...
...
pop3d/extra.c
View file @
12c3088
...
...
@@ -82,10 +82,11 @@ pop3d_cmd (const char *cmd)
/* This is called if GNU POP3 needs to quit without going to the UPDATE stage.
This is used for conditions such as out of memory, a broken socket, or
being killed on a signal */
int
pop3d_abquit
(
int
reason
)
{
/* Unlock spool */
pop3d_unlock
();
mailbox_close
(
mbox
);
mailbox_destroy
(
&
mbox
);
...
...
@@ -96,11 +97,6 @@ pop3d_abquit (int reason)
syslog
(
LOG_ERR
,
"Out of memory"
);
break
;
case
ERR_DEAD_SOCK
:
fprintf
(
ofile
,
"-ERR Socket closed, quitting
\r\n
"
);
syslog
(
LOG_ERR
,
"Socket closed"
);
break
;
case
ERR_SIGNAL
:
fprintf
(
ofile
,
"-ERR Quitting on signal
\r\n
"
);
syslog
(
LOG_ERR
,
"Quitting on signal"
);
...
...
@@ -120,7 +116,7 @@ pop3d_abquit (int reason)
case
ERR_MBOX_SYNC
:
syslog
(
LOG_ERR
,
"Mailbox was updated by other party: %s"
,
username
);
fprintf
(
ofile
,
"-ERR Mailbox updated by other party or corrupt
\r\n
"
);
fprintf
(
ofile
,
"-ERR
[OUT-SYNC]
Mailbox updated by other party or corrupt
\r\n
"
);
break
;
default:
...
...
@@ -129,8 +125,6 @@ pop3d_abquit (int reason)
break
;
}
if
(
ofile
)
fflush
(
ofile
);
closelog
();
exit
(
1
);
}
...
...
@@ -149,8 +143,7 @@ pop3d_usage (char *argv0)
printf
(
" -p, --port=PORT specifies port to listen on, implies -d
\n
"
);
printf
(
" defaults to 110, which need not be specified
\n
"
);
printf
(
" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds
\n
"
);
printf
(
" TIMEOUT must be at least 600 (10 minutes) or
\n
"
);
printf
(
" it will be disabled
\n
"
);
printf
(
" TIMEOUT default is 600 (10 minutes)
\n
"
);
printf
(
" -v, --version display version information and exit
\n
"
);
printf
(
"
\n
Report bugs to bug-mailutils@gnu.org
\n
"
);
exit
(
0
);
...
...
@@ -158,7 +151,7 @@ pop3d_usage (char *argv0)
/* Default signal handler to call the pop3d_abquit() function */
void
RETSIGTYPE
pop3d_signal
(
int
signo
)
{
(
void
)
signo
;
...
...
@@ -167,43 +160,75 @@ pop3d_signal (int signo)
}
/* Gets a line of input from the client */
/* We can also implement PIPELINING by keeping a static buffer.
Implementing this cost an extra allocation with more uglier code.
Is it worth it? How many clients actually use PIPELINING?
*/
char
*
pop3d_readline
(
int
fd
)
{
fd_set
rfds
;
struct
timeval
tv
;
char
buf
[
512
],
*
ret
=
NULL
;
int
nread
;
int
total
=
0
;
int
available
;
FD_ZERO
(
&
rfds
);
FD_SET
(
fd
,
&
rfds
);
tv
.
tv_sec
=
timeout
;
tv
.
tv_usec
=
0
;
do
static
char
*
buffer
=
NULL
;
/* Note: This buffer is never free()d. */
static
size_t
total
=
0
;
char
*
nl
;
char
*
line
;
size_t
len
;
nl
=
memchr
(
buffer
,
'\n'
,
total
);
if
(
!
nl
)
{
if
(
timeout
>
0
)
/* Need to refill the buffer. */
do
{
available
=
select
(
fd
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
if
(
!
available
)
pop3d_abquit
(
ERR_TIMEOUT
);
char
buf
[
512
];
int
nread
;
if
(
timeout
)
{
int
available
;
fd_set
rfds
;
struct
timeval
tv
;
FD_ZERO
(
&
rfds
);
FD_SET
(
fd
,
&
rfds
);
tv
.
tv_sec
=
timeout
;
tv
.
tv_usec
=
0
;
available
=
select
(
fd
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
if
(
!
available
)
pop3d_abquit
(
ERR_TIMEOUT
);
else
if
(
available
==
-
1
)
{
if
(
errno
==
EINTR
)
continue
;
pop3d_abquit
(
ERR_NO_OFILE
);
}
}
errno
=
0
;
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
nread
<
1
)
{
if
(
errno
==
EINTR
)
continue
;
pop3d_abquit
(
ERR_NO_OFILE
);
}
buf
[
nread
]
=
'\0'
;
buffer
=
realloc
(
buffer
,
(
total
+
nread
+
1
)
*
sizeof
(
*
buffer
));
if
(
buffer
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
memcpy
(
buffer
+
total
,
buf
,
nread
+
1
);
/* copy the null too. */
total
+=
nread
;
}
nread
=
read
(
fd
,
buf
,
sizeof
(
buf
)
-
1
);
if
(
nread
<
1
)
pop3d_abquit
(
ERR_DEAD_SOCK
);
buf
[
nread
]
=
'\0'
;
ret
=
realloc
(
ret
,
(
total
+
nread
+
1
)
*
sizeof
(
char
));
if
(
ret
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
memcpy
(
ret
+
total
,
buf
,
nread
+
1
);
total
+=
nread
;
while
((
nl
=
memchr
(
buffer
,
'\n'
,
total
))
==
NULL
);
}
while
(
memchr
(
buf
,
'\n'
,
nread
)
==
NULL
);
return
ret
;
nl
++
;
len
=
nl
-
buffer
;
line
=
calloc
(
len
+
1
,
sizeof
(
*
line
));
memcpy
(
line
,
buffer
,
len
);
/* copy the newline too. */
line
[
len
]
=
'\0'
;
total
-=
len
;
memmove
(
buffer
,
nl
,
total
);
return
line
;
}
...
...
pop3d/list.c
View file @
12c3088
...
...
@@ -23,10 +23,10 @@ int
pop3d_list
(
const
char
*
arg
)
{
size_t
mesgno
;
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
size_t
size
=
0
;
size_t
lines
=
0
;
message_t
msg
;
attribute_t
attr
;
if
(
state
!=
TRANSACTION
)
return
ERR_WRONG_STATE
;
...
...
pop3d/pop3d.c
View file @
12c3088
...
...
@@ -17,24 +17,15 @@
#include "pop3d.h"
/* Save some line space. */
typedef
struct
sockaddr_in
SA
;
/* Declared in <pop3d.h>. */
mailbox_t
mbox
;
unsigned
int
port
;
unsigned
int
timeout
;
size_t
timeout
;
int
state
;
char
*
username
;
int
ifile
;
FILE
*
ofile
;
time_t
curr_time
;
char
*
md5shared
;
volatile
unsigned
int
children
;
/* Number of child processes. */
unsigned
int
children
=
0
;
volatile
size_t
children
;
static
struct
option
long_options
[]
=
{
...
...
@@ -51,17 +42,22 @@ const char *short_options ="d::hip:t:v";
static
int
syslog_error_printer
__P
((
const
char
*
fmt
,
va_list
ap
));
#ifndef DEFMAXCHILDREN
# define DEFMAXCHILDREN 10
/* Default maximum number of children */
#endif
int
main
(
int
argc
,
char
**
argv
)
{
struct
group
*
gr
;
static
int
mode
=
INTERACTIVE
;
size_t
maxchildren
=
20
;
size_t
maxchildren
=
DEFMAXCHILDREN
;
int
c
=
0
;
int
status
=
OK
;
unsigned
int
port
;
port
=
110
;
/* Default POP3 port. */
timeout
=
0
;
/* Default timeout of
0. */
timeout
=
600
;
/* Default timeout of 60
0. */
while
((
c
=
getopt_long
(
argc
,
argv
,
short_options
,
long_options
,
NULL
))
!=
-
1
)
...
...
@@ -70,9 +66,10 @@ main (int argc, char **argv)
{
case
'd'
:
mode
=
DAEMON
;
maxchildren
=
optarg
?
strtoul
(
optarg
,
NULL
,
10
)
:
10
;
if
(
maxchildren
<=
0
)
maxchildren
=
10
;
if
(
optarg
)
maxchildren
=
strtoul
(
optarg
,
NULL
,
10
);
if
(
maxchildren
==
0
)
maxchildren
=
DEFMAXCHILDREN
;
break
;
case
'h'
:
...
...
@@ -106,13 +103,13 @@ main (int argc, char **argv)
gr
=
getgrnam
(
"mail"
);
if
(
gr
==
NULL
)
{
perror
(
"Error getting group"
);
perror
(
"Error getting
mail
group"
);
exit
(
1
);
}
if
(
setgid
(
gr
->
gr_gid
)
==
-
1
)
{
perror
(
"Error setting group"
);
perror
(
"Error setting
mail
group"
);
exit
(
1
);
}
...
...
@@ -134,25 +131,25 @@ main (int argc, char **argv)
signal
(
SIGTERM
,
pop3d_signal
);
signal
(
SIGSTOP
,
pop3d_signal
);
signal
(
SIGPIPE
,
pop3d_signal
);
if
(
timeout
<
600
)
/* RFC 1939 says no less than 10 minutes. */
timeout
=
0
;
/* So we'll turn it off. */
signal
(
SIGABRT
,
pop3d_signal
);
if
(
mode
==
DAEMON
)
pop3d_daemon_init
();
/*
Change
directory. */
/*
Make sure that to be in the root
directory. */
chdir
(
"/"
);
/* Set up for syslog. */
openlog
(
"gnu-pop3d"
,
LOG_PID
,
LOG_FACILITY
);
mu_error_set_print
(
syslog_error_printer
);
/* Redirect any stdout error from the library to syslog, they
should not go to the client. */
mu_error_set_print
(
syslog_error_printer
);
umask
(
S_IROTH
|
S_IWOTH
|
S_IXOTH
);
/* 007 */
/* Actually run the daemon. */
if
(
mode
==
DAEMON
)
pop3d_daemon
(
maxchildren
);
pop3d_daemon
(
maxchildren
,
port
);
/* exit (0) -- no way out of daemon except a signal. */
else
status
=
pop3d_mainloop
(
fileno
(
stdin
),
fileno
(
stdout
));
...
...
@@ -167,8 +164,6 @@ void
pop3d_daemon_init
(
void
)
{
pid_t
pid
;
unsigned
int
i
;
#define MAXFD 64
pid
=
fork
();
if
(
pid
==
-
1
)
...
...
@@ -183,6 +178,8 @@ pop3d_daemon_init (void)
signal
(
SIGHUP
,
SIG_IGN
);
/* Ignore SIGHUP. */
/* The second fork is to guarantee that the daemon cannot acquire a
controlling terminal. */
pid
=
fork
();
if
(
pid
==
-
1
)
{
...
...
@@ -193,9 +190,18 @@ pop3d_daemon_init (void)
exit
(
0
);
/* Parent exits. */
/* Close inherited file descriptors. */
for
(
i
=
0
;
i
<
MAXFD
;
++
i
)
close
(
i
);
{
size_t
i
;
#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
size_t
fdlimit
=
sysconf
(
_SC_OPEN_MAX
);
#else
size_t
fdlimit
=
64
;
#endif
for
(
i
=
0
;
i
<
fdlimit
;
++
i
)
close
(
i
);
}
/* SIGCHLD is not ignore but rather use to do some simple load balancing. */
#ifdef HAVE_SIGACTION
{
struct
sigaction
act
;
...
...
@@ -211,23 +217,21 @@ pop3d_daemon_init (void)
/* The main part of the daemon. This function reads input from the client and
executes the proper functions. Also handles the bulk of error reporting. */
int
pop3d_mainloop
(
int
infile
,
int
outfile
)
{
int
status
=
OK
;
char
*
buf
,
*
arg
,
*
cmd
;
struct
hostent
*
htbuf
;
char
*
local_hostname
;
/* Reset hup to exit. */
signal
(
SIGHUP
,
pop3d_signal
)
;
ifile
=
infile
;
ofile
=
fdopen
(
outfile
,
"w"
);
if
(
ofile
==
NULL
)
pop3d_abquit
(
ERR_NO_OFILE
);
state
=
AUTHORIZATION
;
curr_time
=
time
(
NULL
);
/* FIXME: Retreive hostname with getpeername() and log. */
syslog
(
LOG_INFO
,
"Incoming connection opened"
);
/* log information on the connecting client */
...
...
@@ -242,46 +246,61 @@ pop3d_mainloop (int infile, int outfile)
}
/* Prepare the shared secret for APOP. */
local_hostname
=
malloc
(
MAXHOSTNAMELEN
+
1
);
if
(
local_hostname
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
{
char
*
local_hostname
;
local_hostname
=
malloc
(
MAXHOSTNAMELEN
+
1
);
if
(
local_hostname
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
gethostname
(
local_hostname
,
MAXHOSTNAMELEN
);
htbuf
=
gethostbyname
(
local_hostname
);
if
(
htbuf
)
/* Get our canonical hostname. */
{
free
(
local_hostname
);
local_hostname
=
strdup
(
htbuf
->
h_name
);
struct
hostent
*
htbuf
;
gethostname
(
local_hostname
,
MAXHOSTNAMELEN
);
htbuf
=
gethostbyname
(
local_hostname
);
if
(
htbuf
)
{
free
(
local_hostname
);
local_hostname
=
strdup
(
htbuf
->
h_name
);
}
}
md5shared
=
malloc
(
strlen
(
local_hostname
)
+
51
);
if
(
md5shared
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
md5shared
=
malloc
(
strlen
(
local_hostname
)
+
51
);
if
(
md5shared
==
NULL
)
pop3d_abquit
(
ERR_NO_MEM
);
snprintf
(
md5shared
,
strlen
(
local_hostname
)
+
50
,
"<%u.%u@%s>"
,
getpid
(),
(
int
)
time
(
NULL
),
local_hostname
);
free
(
local_hostname
);
snprintf
(
md5shared
,
strlen
(
local_hostname
)
+
50
,
"<%u.%u@%s>"
,
getpid
(),
(
unsigned
)
time
(
NULL
),
local_hostname
);
free
(
local_hostname
);
}
/* Lets boogie. */
fprintf
(
ofile
,
"+OK POP3 Ready %s
\r\n
"
,
md5shared
);
while
(
state
!=
UPDATE
)
{
char
*
buf
,
*
arg
,
*
cmd
;
fflush
(
ofile
);
status
=
OK
;
buf
=
pop3d_readline
(
ifile
);
cmd
=
pop3d_cmd
(
buf
);
arg
=
pop3d_args
(
buf
);
/* The mailbox size needs to be check to make sure that we are in
sync. Some other applications may not respect the *.lock or
the lock may be stale because downloading on slow modem.
We rely on the size of the mailbox for the check and bail if out
of sync. */
if
(
state
==
TRANSACTION
&&
!
mailbox_is_updated
(
mbox
))
{
static
off_t
mailbox_size
;
off_t
newsize
=
0
;
mailbox_get_size
(
mbox
,
&
newsize
);
/* Did we shrink? */
/* Did we shrink?
First time save the size.
*/
if
(
!
mailbox_size
)
mailbox_size
=
newsize
;
else
if
(
newsize
<
mailbox_size
)
pop3d_abquit
(
ERR_MBOX_SYNC
);
else
if
(
newsize
<
mailbox_size
)
/* FIXME: Should it be a != ? */
pop3d_abquit
(
ERR_MBOX_SYNC
);
/* Out of sync, Bail out. */
}
if
(
strlen
(
arg
)
>
POP_MAXCMDLEN
||
strlen
(
cmd
)
>
POP_MAXCMDLEN
)
...
...
@@ -318,7 +337,7 @@ pop3d_mainloop (int infile, int outfile)
status
=
ERR_BAD_CMD
;
if
(
status
==
OK
)
fflush
(
ofile
);
;
/* Everything is good. */
else
if
(
status
==
ERR_WRONG_STATE
)
fprintf
(
ofile
,
"-ERR "
BAD_STATE
"
\r\n
"
);
else
if
(
status
==
ERR_BAD_ARGS
)
...
...
@@ -347,7 +366,6 @@ pop3d_mainloop (int infile, int outfile)
free
(
arg
);
}
fflush
(
ofile
);
return
(
status
!=
OK
);
}
...
...
@@ -355,11 +373,10 @@ pop3d_mainloop (int infile, int outfile)
(default 110) then executes a pop3d_mainloop() upon accepting a connection.
It starts maxchildren child processes to listen to and accept socket
connections. */
void
pop3d_daemon
(
unsigned
int
maxchildren
)
pop3d_daemon
(
unsigned
int
maxchildren
,
unsigned
int
port
)
{
SA
server
,
client
;
struct
sockaddr_in
server
,
client
;
pid_t
pid
;
int
listenfd
,
connfd
;
size_t
size
;
...
...
@@ -394,7 +411,7 @@ pop3d_daemon (unsigned int maxchildren)
{
if
(
children
>
maxchildren
)
{
syslog
(
LOG_ERR
,
"too many children
"
);
syslog
(
LOG_ERR
,
"too many children
(%d)"
,
children
);
pause
();
continue
;
}
...
...
pop3d/pop3d.h
View file @
12c3088
...
...
@@ -151,13 +151,12 @@
#define ERR_MBOX_LOCK 8
#define ERR_TOO_LONG 9
#define ERR_NO_MEM 10
#define ERR_DEAD_SOCK 11
#define ERR_SIGNAL 12
#define ERR_FILE 13
#define ERR_NO_OFILE 14
#define ERR_TIMEOUT 15
#define ERR_UNKNOWN 16
#define ERR_MBOX_SYNC 17
#define ERR_SIGNAL 11
#define ERR_FILE 12
#define ERR_NO_OFILE 13
#define ERR_TIMEOUT 14
#define ERR_UNKNOWN 15
#define ERR_MBOX_SYNC 16
#ifndef __P
# ifdef __STDC__
...
...
@@ -169,40 +168,39 @@
extern
mailbox_t
mbox
;
extern
unsigned
int
port
;
extern
unsigned
int
timeout
;
extern
int
state
;
extern
char
*
username
;
extern
int
ifile
;
extern
FILE
*
ofile
;
extern
time_t
curr_time
;
extern
char
*
md5shared
;
extern
unsigned
int
children
;
extern
int
pop3d_dele
__P
((
const
char
*
arg
));
extern
int
pop3d_list
__P
((
const
char
*
arg
));
extern
int
pop3d_noop
__P
((
const
char
*
arg
));
extern
int
pop3d_quit
__P
((
const
char
*
arg
));
extern
int
pop3d_retr
__P
((
const
char
*
arg
));
extern
int
pop3d_rset
__P
((
const
char
*
arg
));
extern
int
pop3d_stat
__P
((
const
char
*
arg
));
extern
int
pop3d_top
__P
((
const
char
*
arg
));
extern
int
pop3d_uidl
__P
((
const
char
*
arg
));
extern
int
pop3d_user
__P
((
const
char
*
arg
));
extern
int
pop3d_apop
__P
((
const
char
*
arg
));
extern
int
pop3d_auth
__P
((
const
char
*
arg
));
extern
int
pop3d_capa
__P
((
const
char
*
arg
));
extern
char
*
pop3d_args
__P
((
const
char
*
cmd
));
extern
char
*
pop3d_cmd
__P
((
const
char
*
cmd
));
extern
int
pop3d_abquit
__P
((
int
reason
));
extern
int
pop3d_lock
__P
((
void
));
extern
int
pop3d_unlock
__P
((
void
));
extern
int
pop3d_mainloop
__P
((
int
infile
,
int
outfile
));
extern
void
pop3d_daemon
__P
((
unsigned
int
maxchildren
));
extern
void
pop3d_usage
__P
((
char
*
argv0
));
extern
void
pop3d_signal
__P
((
int
));
extern
void
pop3d_sigchld
__P
((
int
));
extern
void
pop3d_daemon_init
__P
((
void
));
extern
char
*
pop3d_apopuser
__P
((
const
char
*
user
));
extern
char
*
pop3d_readline
__P
((
int
fd
));
extern
volatile
size_t
children
;
extern
int
pop3d_dele
__P
((
const
char
*
));
extern
int
pop3d_list
__P
((
const
char
*
));
extern
int
pop3d_noop
__P
((
const
char
*
));
extern
int
pop3d_quit
__P
((
const
char
*
));
extern
int
pop3d_retr
__P
((
const
char
*
));
extern
int
pop3d_rset
__P
((
const
char
*
));
extern
int
pop3d_stat
__P
((
const
char
*
));
extern
int
pop3d_top
__P
((
const
char
*
));
extern
int
pop3d_uidl
__P
((
const
char
*
));
extern
int
pop3d_user
__P
((
const
char
*
));
extern
int
pop3d_apop
__P
((
const
char
*
));
extern
int
pop3d_auth
__P
((
const
char
*
));
extern
int
pop3d_capa
__P
((
const
char
*
));
extern
char
*
pop3d_args
__P
((
const
char
*
));
extern
char
*
pop3d_cmd
__P
((
const
char
*
));
extern
int
pop3d_abquit
__P
((
int
));
extern
int
pop3d_lock
__P
((
void
));
extern
int
pop3d_touchlock
__P
((
void
));
extern
int
pop3d_unlock
__P
((
void
));
extern
int
pop3d_mainloop
__P
((
int
,
int
));
extern
void
pop3d_daemon
__P
((
size_t
,
unsigned
int
));
extern
void
pop3d_usage
__P
((
char
*
));
extern
RETSIGTYPE
pop3d_signal
__P
((
int
));
extern
RETSIGTYPE
pop3d_sigchld
__P
((
int
));
extern
void
pop3d_daemon_init
__P
((
void
));
extern
char
*
pop3d_apopuser
__P
((
const
char
*
));
extern
char
*
pop3d_readline
__P
((
int
));
#endif
/* _POP3D_H */
...
...
pop3d/quit.c
View file @
12c3088
...
...
@@ -32,6 +32,7 @@ pop3d_quit (const char *arg)
if
(
state
==
TRANSACTION
)
{
pop3d_unlock
();
if
(
mailbox_expunge
(
mbox
)
!=
0
)
err
=
ERR_FILE
;
if
(
mailbox_close
(
mbox
)
!=
0
)
...
...
pop3d/retr.c
View file @
12c3088
...
...
@@ -25,9 +25,9 @@ pop3d_retr (const char *arg)
size_t
mesgno
,
n
;
char
*
buf
;
size_t
buflen
=
BUFFERSIZE
;
message_t
msg
;
attribute_t
attr
;
stream_t
stream
;
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
stream_t
stream
=
NULL
;
off_t
off
;
if
((
strlen
(
arg
)
==
0
)
||
(
strchr
(
arg
,
' '
)
!=
NULL
))
...
...
pop3d/rset.c
View file @
12c3088
...
...
@@ -35,8 +35,8 @@ pop3d_rset (const char *arg)
for
(
i
=
1
;
i
<=
total
;
i
++
)
{
message_t
msg
;
attribute_t
attr
;
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
mailbox_get_message
(
mbox
,
i
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
if
(
attribute_is_deleted
(
attr
))
...
...
pop3d/signal.c
View file @
12c3088
...
...
@@ -18,21 +18,17 @@
#include "pop3d.h"
void
RETSIGTYPE
pop3d_sigchld
(
int
signo
)
{
pid_t
pid
;
int
status
;
int
old_errno
=
errno
;
(
void
)
signo
;
errno
=
0
;
while
(
(
pid
=
waitpid
(
-
1
,
&
status
,
WNOHANG
))
>
0
)
--
children
;
#ifndef HAVE_SIGACTION
/* On some system, signal implements the unreliab
e sema
tic and
/* On some system, signal implements the unreliab
le seman
tic and
has to be rearm. */
signal
(
SIGCHLD
,
pop3d_sigchld
);
signal
(
signo
,
pop3d_sigchld
);
#endif
errno
=
old_errno
;
}
...
...
pop3d/stat.c
View file @
12c3088
...
...
@@ -28,8 +28,8 @@ pop3d_stat (const char *arg)
size_t
total
=
0
;
size_t
num
=
0
;
size_t
tsize
=
0
;
message_t
msg
;
attribute_t
attr
;
message_t
msg
=
NULL
;
attribute_t
attr
=
NULL
;
if
(
strlen
(
arg
)
!=
0
)
return
ERR_BAD_ARGS
;
...
...
@@ -45,6 +45,8 @@ pop3d_stat (const char *arg)
{
mailbox_get_message
(
mbox
,
mesgno
,
&
msg
);
message_get_attribute
(
msg
,
&
attr
);
/* rfc1939: Note that messages marked as deleted are not counted in
either total. */
if
(
!
attribute_is_deleted
(
attr
))
{
message_size
(
msg
,
&
size
);
...
...
@@ -53,8 +55,6 @@ pop3d_stat (const char *arg)
num
++
;
}
}
/* rfc1939: Note that messages marked as deleted are not counted in either
total. */
fprintf
(
ofile
,
"+OK %d %d
\r\n
"
,
num
,
tsize
);
return
OK
;
...
...
pop3d/user.c
View file @
12c3088
...
...
@@ -82,10 +82,7 @@ pop3d_user (const char *arg)
char
*
buf
,
pass
[
POP_MAXCMDLEN
],
*
tmp
,
*
cmd
;
struct
passwd
*
pw
;
int
status
;
#ifdef USE_LIBPAM
pam_handle_t
*
pamh
;
int
pamerror
;
#endif
/* !USE_LIBPAM */
int
lockit
=
1
;
if
(
state
!=
AUTHORIZATION
)
return
ERR_WRONG_STATE
;
...
...
@@ -110,6 +107,8 @@ pop3d_user (const char *arg)
else
{
strncpy
(
pass
,
tmp
,
POP_MAXCMDLEN
);
/* strncpy () is lame, make sure the string is null terminated. */
pass
[
POP_MAXCMDLEN
-
1
]
=
'\0'
;
free
(
tmp
);
}
...
...
@@ -151,35 +150,34 @@ pop3d_user (const char *arg)
}
}
#else
/* !USE_LIBPAM */
_user
=
(
char
*
)
arg
;
_pwd
=
pass
;
/* libpam doesn't log to LOG_MAIL */
closelog
();
pamerror
=
pam_start
(
"gnu-pop3d"
,
arg
,
&
PAM_conversation
,
&
pamh
);
PAM_ERROR
;
pamerror
=
pam_authenticate
(
pamh
,
0
);
PAM_ERROR
;
pamerror
=
pam_acct_mgmt
(
pamh
,
0
);
PAM_ERROR
;
pamerror
=
pam_setcred
(
pamh
,
PAM_ESTABLISH_CRED
);
PAM_ERROR
;
pam_errlab:
pam_end
(
pamh
,
PAM_SUCCESS
);
openlog
(
"gnu-pop3d"
,
LOG_PID
,
LOG_FACILITY
);
if
(
pamerror
!=
PAM_SUCCESS
)
{
syslog
(
LOG_INFO
,
"User '%s': authentication failed"
,
_user
);
return
ERR_BAD_LOGIN
;
}
{
pam_handle_t
*
pamh
;
int
pamerror
;
_user
=
(
char
*
)
arg
;
_pwd
=
pass
;
pamerror
=
pam_start
(
"gnu-pop3d"
,
arg
,
&
PAM_conversation
,
&
pamh
);
PAM_ERROR
;
pamerror
=
pam_authenticate
(
pamh
,
0
);
PAM_ERROR
;
pamerror
=
pam_acct_mgmt
(
pamh
,
0
);
PAM_ERROR
;
pamerror
=
pam_setcred
(
pamh
,
PAM_ESTABLISH_CRED
);
PAM_ERROR
;
pam_errlab:
pam_end
(
pamh
,
PAM_SUCCESS
);
if
(
pamerror
!=
PAM_SUCCESS
)
{
syslog
(
LOG_INFO
,
"User '%s': authentication failed"
,
_user
);
return
ERR_BAD_LOGIN
;
}
}
#endif
/* USE_LIBPAM */
if
(
pw
!=
NULL
&&
pw
->
pw_uid
>
1
)
setuid
(
pw
->
pw_uid
);
if
(
mailbox_create_default
(
&
mbox
,
arg
)
!=
0
)
{
state
=
AUTHORIZATION
;
return
ERR_UNKNOWN
;
}
else
if
((
status
=
mailbox_open
(
mbox
,
MU_STREAM_RDWR
))
!=
0
)
if
((
status
=
mailbox_create_default
(
&
mbox
,
arg
)
!=
0
)
||
(
status
=
mailbox_open
(
mbox
,
MU_STREAM_RDWR
)
!=
0
))
{
mailbox_destroy
(
&
mbox
);
/* For non existent mailbox, we fake. */
...
...
@@ -197,6 +195,16 @@ pam_errlab:
state
=
AUTHORIZATION
;
return
ERR_MBOX_LOCK
;
}
lockit
=
0
;
/* Do not attempt to lock /dev/null ! */
}
if
(
lockit
&&
pop3d_lock
())
{
mailbox_close
(
mbox
);
mailbox_destroy
(
&
mbox
);
state
=
AUTHORIZATION
;
free
(
cmd
);
return
ERR_MBOX_LOCK
;
}
username
=
strdup
(
arg
);
...
...
@@ -204,16 +212,16 @@ pam_errlab:
pop3d_abquit
(
ERR_NO_MEM
);
state
=
TRANSACTION
;
if
(
pw
!=
NULL
&&
pw
->
pw_uid
>
1
)
setuid
(
pw
->
pw_uid
);
fprintf
(
ofile
,
"+OK opened mailbox for %s
\r\n
"
,
username
);
/* mailbox name */
/* mailbox name */
{
url_t
url
=
NULL
;
size_t
total
=
0
;
mailbox_get_url
(
mbox
,
&
url
);
syslog
(
LOG_INFO
,
"User '%s' logged in with mailbox '%s'"
,
username
,
url_to_string
(
url
));
mailbox_messages_count
(
mbox
,
&
total
);
syslog
(
LOG_INFO
,
"User '%s' logged in with mailbox '%s' (%d msgs)"
,
username
,
url_to_string
(
url
),
total
);
}
return
OK
;
}
...
...
Please
register
or
sign in
to post a comment