Commit b0ccfea9 b0ccfea9cb042f8a95fe6dbad2a5597362bc2b65 by Wojciech Polak

Added TLS/SSL support (via GnuTLS)

1 parent 681f85c7
2003-01-13 Wojciech Polak
* auth/tls.c: New file. Added main TLS/SSL code (via GnuTLS).
* include/mailutils/tls.h: New file. TLS header file.
* auth/Makefile.am: Updated.
* include/mailutils/Makefile.am: Likewise.
* pop3d/pop3d.c: Added TLS support.
* pop3d/pop3d.h: include <mailutils/tls.h>
(pop3d_stls): New prototype.
* pop3d/stls.c: New file. The STLS command support.
* pop3d/extra.c (pop3d_init_tls_server): New function.
(pop3d_deinit_tls_server): New function.
(pop3d_outf): Added TLS support (GnuTLS).
(pop3d_readline): Added TLS support (GnuTLS).
* pop3d/capa.c (pop3d_capa): Added STLS.
* pop3d/Makefile.am: Updated.
* m4/tls.m4: New file. Implements MU_CHECK_TLS defun.
* m4/Makefile.am: Updated.
* configure.ac: Added GnuTLS support (--with-gnutls).
2003-01-13 Sergey Poznyakoff
* m4/gssapi.m4: Fixed typo.
......
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2002 Free Software Foundation, Inc.
## Copyright (C) 2002, 2003 Free Software Foundation, Inc.
##
## GNU Mailtuils is free software; you can redistribute it and/or
## 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.
##
## 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
......@@ -25,6 +25,7 @@ lib_LTLIBRARIES = libmuauth.la
libmuauth_la_SOURCES = \
pam.c \
sql.c \
tls.c \
virtual.c
libmuauth_la_LIBADD = @LTLIBINTL@
......
/* 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 Library 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 Library 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 */
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mailutils/argp.h>
#include <mailutils/error.h>
#include <mailutils/mu_auth.h>
#include <mailutils/tls.h>
#include <mailutils/nls.h>
#ifdef WITH_TLS
#define DH_BITS 768
static gnutls_dh_params dh_params;
static gnutls_certificate_server_credentials x509_cred;
static char *ssl_cert = NULL;
static char *ssl_key = NULL;
static char *ssl_cafile = NULL;
#define ARG_SSL_CERT 1
#define ARG_SSL_KEY 2
#define ARG_SSL_CAFILE 3
static struct argp_option _tls_argp_options[] = {
{NULL, 0, NULL, 0, N_("Encryption options"), 0},
{"ssl-cert", ARG_SSL_CERT, N_("FILE"), 0,
N_("Specify SSL certificate file"), 0},
{"ssl-key", ARG_SSL_KEY, N_("KEY"), 0,
N_("Specify SSL certificate key"), 0},
{"ssl-cafile", ARG_SSL_CAFILE, N_("FILE"), 0,
N_("Specify trusted CAs file"), 0},
{NULL, 0, NULL, 0, NULL, 0}
};
static error_t
_tls_argp_parser (int key, char *arg, struct argp_state *state)
{
switch (key)
{
case ARG_SSL_CERT:
ssl_cert = arg;
break;
case ARG_SSL_KEY:
ssl_key = arg;
break;
case ARG_SSL_CAFILE:
ssl_cafile = arg;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp _tls_argp = {
_tls_argp_options,
_tls_argp_parser
};
static struct argp_child _tls_argp_child = {
&_tls_argp,
0,
NULL,
0
};
void
mu_tls_init_argp ()
{
if (mu_register_capa ("tls", &_tls_argp_child))
{
mu_error (_("INTERNAL ERROR: cannot register argp capability tls"));
abort ();
}
}
int
mu_check_tls_environment (void)
{
/* Return: zero means NOT READY, one means READY */
if (ssl_cert && ssl_key)
{
struct stat st;
if (stat (ssl_cert, &st) == -1)
return 0;
if (!(st.st_mode & S_IFREG) || !(st.st_mode & S_IFLNK))
{
mu_error (_("%s is not a regular file or a symbolic link."),
ssl_cert);
return 0;
}
if ((st.st_mode & S_IRWXG) || (st.st_mode & S_IRWXO))
{
mu_error (_("Wrong permissions on %s. Set 0600."), ssl_cert);
return 0;
}
if (stat (ssl_key, &st) == -1)
return 0;
if (!(st.st_mode & S_IFREG) || !(st.st_mode & S_IFLNK))
{
mu_error (_("%s is not a regular file or a symbolic link."),
ssl_key);
return 0;
}
if ((st.st_mode & S_IRWXG) || (st.st_mode & S_IRWXO))
{
mu_error (_("Wrong permissions on %s. Set 0600."), ssl_key);
return 0;
}
}
else
return 0;
return 1;
}
int
mu_init_tls_libs (void)
{
int rs = 1;
rs = gnutls_global_init ();
if (rs == 0) /* Reverse for tls_available */
rs = 1;
return rs; /* Returns 1 on success */
}
int
mu_deinit_tls_libs (void)
{
gnutls_global_deinit ();
}
static void
generate_dh_params (void)
{
gnutls_datum prime, generator;
gnutls_dh_params_init (&dh_params);
gnutls_dh_params_generate (&prime, &generator, DH_BITS);
gnutls_dh_params_set (dh_params, prime, generator, DH_BITS);
free (prime.data);
free (generator.data);
}
static gnutls_session
initialize_tls_session (void)
{
gnutls_session session = 0;
gnutls_init (&session, GNUTLS_SERVER);
gnutls_set_default_priority (session);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
gnutls_dh_set_prime_bits (session, DH_BITS);
return (gnutls_session) session;
}
gnutls_session
mu_init_tls_server (int fd_in, int fd_out)
{
int rs = 0;
gnutls_session session = 0;
gnutls_certificate_allocate_credentials (&x509_cred);
if (ssl_cafile)
gnutls_certificate_set_x509_trust_file (x509_cred, ssl_cafile,
GNUTLS_X509_FMT_PEM);
gnutls_certificate_set_x509_key_file (x509_cred,
ssl_cert, ssl_key,
GNUTLS_X509_FMT_PEM);
generate_dh_params ();
gnutls_certificate_set_dh_params (x509_cred, dh_params);
session = initialize_tls_session ();
gnutls_transport_set_ptr2 (session, fd_in, fd_out);
rs = gnutls_handshake (session);
if (rs < 0)
{
gnutls_deinit (session);
mu_error (_("TLS/SSL handshake failed!"));
gnutls_perror (rs);
return 0; /* failed */
}
return (gnutls_session) session;
}
void
mu_deinit_tls_server (gnutls_session session)
{
if (session)
{
gnutls_bye (session, GNUTLS_SHUT_RDWR);
gnutls_deinit (session);
}
}
#endif /* WITH_TLS */
/* EOF */
# Configuration for GNU mailutils - a suite of utilities for electronic mail
#
# Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
# Copyright (C) 1999, 2000, 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
......@@ -113,6 +113,13 @@ if test "x$WITH_GSSAPI" != "xno"; then
fi
AC_SUBST(AUTHOBJS)
MU_CHECK_TLS
if test "$WITH_GNUTLS" != "no"; then
AUTHLIBS="$AUTHLIBS $TLS_LIBS"
AC_DEFINE(WITH_GNUTLS,1,[Define if mailutils is using GNU TLS])
AC_DEFINE(WITH_TLS,1,[Define if mailutils is using TLS])
fi
AC_ARG_WITH([guile],
AC_HELP_STRING([--without-guile],
[do not build guile interface]),
......
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
## Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
##
## GNU Mailtuils is free software; you can redistribute it and/or
## 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.
##
## 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
......@@ -50,6 +50,7 @@ pkginclude_HEADERS = \
property.h \
registrar.h \
stream.h \
tls.h \
types.h \
url.h
......
/* 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 Library 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 Library 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 */
#ifndef _MAILUTILS_TLS_H
#define _MAILUTILS_TLS_H
#ifdef WITH_TLS
#ifdef WITH_GNUTLS
# include <gnutls/gnutls.h>
#endif /* WITH_GNUTLS */
#endif /* WITH_TLS */
#endif /* _MAILUTILS_TLS_H */
## Process this file with GNU Automake to create Makefile.in
## Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
## Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
##
## GNU Mailtuils is free software; you can redistribute it and/or
## 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.
##
## 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
......@@ -27,6 +27,7 @@ EXTRA_DIST = \
realloc.m4 \
regex.m4 \
utmp.m4 \
tls.m4 \
iconv.m4 \
codeset.m4 \
gettext.m4 \
......
AC_DEFUN(MU_CHECK_TLS,
[
if test "x$WITH_GNUTLS" = x; then
cached=""
AC_ARG_WITH([gnutls],
AC_HELP_STRING([--with-gnutls],
[use GNU TLS library]),
[WITH_GNUTLS=$withval],
[WITH_GNUTLS=no])
if test "$WITH_GNUTLS" != "no"; then
AC_CHECK_HEADER(gnutls/gnutls.h,
[:],
[WITH_GNUTLS=no])
if test "$WITH_GNUTLS" != "no"; then
saved_LIBS=$LIBS
AC_CHECK_LIB(gnutls, gnutls_global_init,
[TLS_LIBS="-lgnutls"],
[WITH_GNUTLS=no])
AC_CHECK_LIB(gcrypt, main,
[TLS_LIBS="$TLS_LIBS -lgcrypt"],
[WITH_GNUTLS=no])
LIBS=$saved_LIBS
fi
fi
else
cached=" (cached) "
fi
AC_MSG_CHECKING([whether to use TLS libraries])
AC_MSG_RESULT(${cached}${WITH_GNUTLS})])
## 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 Mailtuils is free software; you can redistribute it and/or
## 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.
##
## 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
......@@ -25,8 +25,8 @@ EXTRA_PROGRAMS = popauth
SUBDIRS = testsuite
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 signal.c top.c uidl.c \
user.c
list.c lock.c noop.c quit.c retr.c rset.c stat.c stls.c signal.c top.c \
uidl.c user.c
pop3d_LDADD = ../mailbox/libmailbox.la @AUTHLIBS@ ../lib/libmailutils.la @LTLIBINTL@
......
/* 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
......@@ -41,6 +41,12 @@ pop3d_capa (const char *arg)
pop3d_outf ("UIDL\r\n");
pop3d_outf ("RESP-CODES\r\n");
pop3d_outf ("PIPELINING\r\n");
#ifdef WITH_TLS
if (tls_available && tls_done == 0)
pop3d_outf ("STLS\r\n");
#endif /* WITH_TLS */
/* FIXME: This can be Implemented by setting an header field on the
message. */
/*pop3d_outf ("EXPIRE NEVER\r\n"); */
......
......@@ -19,6 +19,9 @@
static FILE *ifile;
static FILE *ofile;
#ifdef WITH_TLS
static gnutls_session sfile;
#endif /* WITH_TLS */
/* Takes a string as input and returns either the remainder of the string
after the first space, or a zero length string if no space */
......@@ -89,7 +92,7 @@ int
pop3d_abquit (int reason)
{
/* Unlock spool */
pop3d_unlock();
pop3d_unlock ();
mailbox_close (mbox);
mailbox_destroy (&mbox);
......@@ -119,7 +122,8 @@ pop3d_abquit (int reason)
case ERR_MBOX_SYNC:
syslog (LOG_ERR, _("Mailbox was updated by other party: %s"), username);
pop3d_outf ("-ERR [OUT-SYNC] Mailbox updated by other party or corrupt\r\n");
pop3d_outf
("-ERR [OUT-SYNC] Mailbox updated by other party or corrupt\r\n");
break;
default:
......@@ -128,19 +132,39 @@ pop3d_abquit (int reason)
break;
}
closelog();
closelog ();
exit (EXIT_FAILURE);
}
void
pop3d_setio (FILE *in, FILE *out)
pop3d_setio (FILE * in, FILE * out)
{
if (!in || !out)
pop3d_abquit (ERR_NO_OFILE);
ifile = in;
ofile = out;
}
}
#ifdef WITH_TLS
int
pop3d_init_tls_server ()
{
sfile =
(gnutls_session) mu_init_tls_server (fileno (ifile), fileno (ofile));
if (!sfile)
return 0;
return 1;
}
void
pop3d_deinit_tls_server ()
{
mu_deinit_tls_server (sfile);
}
#endif /* WITH_TLS */
void
pop3d_flush_output ()
......@@ -169,10 +193,25 @@ pop3d_outf (const char *fmt, ...)
free (buf);
}
}
vfprintf (ofile, fmt, ap);
#ifdef WITH_TLS
if (tls_done)
{
char *buf;
vasprintf (&buf, fmt, ap);
if (buf)
{
gnutls_record_send (sfile, buf, strlen (buf));
free (buf);
}
}
else
#endif /* WITH_TLS */
vfprintf (ofile, fmt, ap);
va_end (ap);
}
/* Gets a line of input from the client, caller should free() */
char *
......@@ -181,7 +220,15 @@ pop3d_readline (char *buffer, size_t size)
char *ptr;
alarm (daemon_param.timeout);
ptr = fgets (buffer, size, ifile);
#ifdef WITH_TLS
if (tls_done)
{
gnutls_record_recv (sfile, buffer, size - 1);
ptr = buffer;
}
else
#endif /* WITH_TLS */
ptr = fgets (buffer, size, ifile);
alarm (0);
/* We should probably check ferror() too, but if ptr is null we
......
......@@ -32,6 +32,11 @@ struct daemon_param daemon_param = {
int debug_mode;
#ifdef WITH_TLS
int tls_available;
int tls_done;
#endif /* WITH_TLS */
/* Number of child processes. */
volatile size_t children;
......@@ -57,6 +62,9 @@ static struct argp argp = {
static const char *pop3d_argp_capa[] = {
"daemon",
"auth",
#ifdef WITH_TLS
"tls",
#endif /* WITH_TLS */
"common",
"mailbox",
"logging",
......@@ -90,6 +98,9 @@ main (int argc, char **argv)
mu_init_nls ();
MU_AUTH_REGISTER_ALL_MODULES();
#ifdef WITH_TLS
mu_tls_init_argp ();
#endif /* WITH_TLS */
mu_argp_parse (&argp, &argc, &argv, 0, pop3d_argp_capa, NULL, &daemon_param);
#ifdef USE_LIBPAM
......@@ -117,7 +128,7 @@ main (int argc, char **argv)
exit (EXIT_FAILURE);
}
}
/* Register the desired formats. */
{
list_t bookie;
......@@ -154,6 +165,13 @@ main (int argc, char **argv)
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)
pop3d_daemon (daemon_param.maxchildren, daemon_param.port);
......@@ -330,6 +348,10 @@ pop3d_mainloop (int fd, FILE *infile, FILE *outfile)
status = pop3d_uidl (arg);
else if (strncasecmp (cmd, "CAPA", 4) == 0)
status = pop3d_capa (arg);
#ifdef WITH_TLS
else if ((strncasecmp (cmd, "STLS", 4) == 0) && tls_available)
status = pop3d_stls (arg);
#endif /* WITH_TLS */
else
status = ERR_BAD_CMD;
......@@ -362,6 +384,11 @@ pop3d_mainloop (int fd, FILE *infile, FILE *outfile)
free (arg);
}
#ifdef WITH_TLS
pop3d_deinit_tls_server ();
mu_deinit_tls_libs ();
#endif /* WITH_TLS */
return (status != OK);
}
......
......@@ -123,6 +123,7 @@
#include <mailutils/registrar.h>
#include <mailutils/url.h>
#include <mailutils/mu_auth.h>
#include <mailutils/tls.h>
#include <mailutils/nls.h>
/* For Berkley DB2 APOP password file */
......@@ -175,6 +176,8 @@ extern char *md5shared;
extern volatile size_t children;
extern struct daemon_param daemon_param;
extern int debug_mode;
extern int tls_available;
extern int tls_done;
extern int pop3d_abquit __P ((int));
extern int pop3d_apop __P ((const char *));
......@@ -193,6 +196,9 @@ extern int pop3d_rset __P ((const char *));
extern RETSIGTYPE pop3d_sigchld __P ((int));
extern RETSIGTYPE pop3d_signal __P ((int));
extern int pop3d_stat __P ((const char *));
#ifdef WITH_TLS
extern int pop3d_stls __P ((const char *));
#endif /* WITH_TLS */
extern int pop3d_top __P ((const char *));
extern int pop3d_touchlock __P ((void));
extern int pop3d_uidl __P ((const char *));
......
/* 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 "pop3d.h"
/* STLS command -- TLS/SSL encryption */
#ifdef WITH_TLS
int
pop3d_stls (const char *arg)
{
if (strlen (arg) != 0)
return ERR_BAD_ARGS;
if (state != AUTHORIZATION)
return ERR_WRONG_STATE;
pop3d_outf ("+OK Begin TLS negotiation\r\n");
pop3d_flush_output ();
tls_done = pop3d_init_tls_server ();
if (!tls_done)
return ERR_UNKNOWN;
return OK;
}
#endif /* WITH_TLS */