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
7ada98e7
...
7ada98e754453cdae3198321b5c1b2f4e55538e4
authored
2003-08-28 19:34:27 +0000
by
Sergey Poznyakoff
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Implemented client TLS stream
1 parent
d1ce780d
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
215 additions
and
22 deletions
auth/tls.c
auth/tls.c
View file @
7ada98e
...
...
@@ -32,6 +32,8 @@
#include <mailutils/nls.h>
#include <mailutils/stream.h>
#include <lbuf.h>
#ifdef WITH_TLS
#include <gnutls/gnutls.h>
...
...
@@ -44,9 +46,10 @@ 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
#define ARG_TLS 1
#define ARG_SSL_CERT 2
#define ARG_SSL_KEY 3
#define ARG_SSL_CAFILE 4
static
struct
argp_option
_tls_argp_options
[]
=
{
{
NULL
,
0
,
NULL
,
0
,
N_
(
"Encryption options"
),
0
},
...
...
@@ -62,8 +65,17 @@ static struct argp_option _tls_argp_options[] = {
static
error_t
_tls_argp_parser
(
int
key
,
char
*
arg
,
struct
argp_state
*
state
)
{
static
int
tls_enable
=
1
;
switch
(
key
)
{
case
ARG_TLS
:
if
(
!
arg
||
strcasecmp
(
arg
,
"yes"
)
==
0
)
tls_enable
=
1
;
else
if
(
strcasecmp
(
arg
,
"no"
)
==
0
)
tls_enable
=
0
;
break
;
case
ARG_SSL_CERT
:
ssl_cert
=
arg
;
break
;
...
...
@@ -76,6 +88,11 @@ _tls_argp_parser (int key, char *arg, struct argp_state *state)
ssl_cafile
=
arg
;
break
;
case
ARGP_KEY_FINI
:
if
(
tls_enable
)
mu_init_tls_libs
();
break
;
default:
return
ARGP_ERR_UNKNOWN
;
}
...
...
@@ -104,6 +121,34 @@ mu_tls_init_argp ()
}
}
static
struct
argp_option
_tls_argp_client_options
[]
=
{
{
"tls"
,
ARG_TLS
,
N_
(
"BOOL"
),
OPTION_ARG_OPTIONAL
,
N_
(
"Enable TLS support"
)
},
{
NULL
,
0
,
NULL
,
0
,
NULL
,
0
}
};
static
struct
argp
_tls_client_argp
=
{
_tls_argp_client_options
,
_tls_argp_parser
};
static
struct
argp_child
_tls_argp_client_child
=
{
&
_tls_client_argp
,
0
,
NULL
,
0
};
void
mu_tls_init_client_argp
()
{
if
(
mu_register_capa
(
"tls"
,
&
_tls_argp_client_child
))
{
mu_error
(
_
(
"INTERNAL ERROR: cannot register argp capability tls"
));
abort
();
}
}
int
mu_check_tls_environment
(
void
)
{
...
...
@@ -142,16 +187,22 @@ mu_check_tls_environment (void)
return
1
;
}
int
mu_tls_enable
=
0
;
int
mu_init_tls_libs
(
void
)
{
return
!
gnutls_global_init
();
/* Returns 1 on success */
if
(
!
mu_tls_enable
)
mu_tls_enable
=
!
gnutls_global_init
();
/* Returns 1 on success */
return
mu_tls_enable
;
}
void
mu_deinit_tls_libs
(
void
)
{
gnutls_global_deinit
();
if
(
mu_tls_enable
)
gnutls_global_deinit
();
mu_tls_enable
=
0
;
}
static
void
...
...
@@ -194,8 +245,10 @@ struct _tls_stream {
int
ifd
;
int
ofd
;
int
last_err
;
struct
_line_buffer
*
lb
;
enum
tls_stream_state
state
;
gnutls_session
session
;
gnutls_session
session
;
stream_t
tcp_str
;
};
...
...
@@ -203,11 +256,16 @@ static void
_tls_destroy
(
stream_t
stream
)
{
struct
_tls_stream
*
s
=
stream_get_owner
(
stream
);
if
(
x509_cred
)
gnutls_certificate_free_credentials
(
x509_cred
);
if
(
s
->
session
&&
s
->
state
==
state_closed
)
{
gnutls_deinit
(
s
->
session
);
s
->
state
=
state_destroyed
;
}
if
(
s
->
tcp_str
)
stream_destroy
(
&
s
->
tcp_str
,
stream_get_owner
(
s
->
tcp_str
));
_auth_lb_destroy
(
&
s
->
lb
);
free
(
s
);
}
...
...
@@ -242,26 +300,30 @@ _tls_readline (stream_t stream, char *optr, size_t osize,
if
(
!
stream
||
s
->
state
!=
state_open
||
osize
<
2
)
return
EINVAL
;
osize
--
;
/* Allow for terminating zero */
ptr
=
optr
;
rdsize
=
0
;
do
if
(
_auth_lb_level
(
s
->
lb
)
==
0
)
{
rc
=
gnutls_record_recv
(
s
->
session
,
ptr
+
rdsize
,
osize
-
rdsize
);
if
(
rc
<
0
)
ptr
=
optr
;
rdsize
=
0
;
do
{
s
->
last_err
=
rc
;
return
EIO
;
rc
=
gnutls_record_recv
(
s
->
session
,
ptr
+
rdsize
,
osize
-
rdsize
);
if
(
rc
<
0
)
{
s
->
last_err
=
rc
;
return
EIO
;
}
rdsize
+=
rc
;
}
rdsize
+=
rc
;
while
(
osize
>
rdsize
&&
rc
>
0
&&
ptr
[
rdsize
-
1
]
!=
'\n'
);
_auth_lb_grow
(
s
->
lb
,
ptr
,
rdsize
);
}
while
(
osize
>
rdsize
&&
rc
>
0
&&
ptr
[
rdsize
-
1
]
!=
'\n'
);
ptr
[
rdsize
]
=
0
;
osize
--
;
/* Allow for terminating zero */
rdsize
=
_auth_lb_readline
(
s
->
lb
,
optr
,
osize
);
optr
[
rdsize
]
=
0
;
if
(
nbytes
)
*
nbytes
=
rdsize
;
return
0
;
}
...
...
@@ -359,6 +421,81 @@ _tls_open (stream_t stream)
return
0
;
}
static
int
prepare_client_session
(
struct
_tls_stream
*
s
)
{
int
rc
;
static
int
protocol_priority
[]
=
{
GNUTLS_TLS1
,
GNUTLS_SSL3
,
0
};
static
int
kx_priority
[]
=
{
GNUTLS_KX_RSA
,
0
};
static
int
cipher_priority
[]
=
{
GNUTLS_CIPHER_3DES_CBC
,
GNUTLS_CIPHER_ARCFOUR_128
,
0
};
static
int
comp_priority
[]
=
{
GNUTLS_COMP_NULL
,
0
};
static
int
mac_priority
[]
=
{
GNUTLS_MAC_SHA
,
GNUTLS_MAC_MD5
,
0
};
gnutls_init
(
&
s
->
session
,
GNUTLS_CLIENT
);
gnutls_protocol_set_priority
(
s
->
session
,
protocol_priority
);
gnutls_cipher_set_priority
(
s
->
session
,
cipher_priority
);
gnutls_compression_set_priority
(
s
->
session
,
comp_priority
);
gnutls_kx_set_priority
(
s
->
session
,
kx_priority
);
gnutls_mac_set_priority
(
s
->
session
,
mac_priority
);
gnutls_certificate_allocate_credentials
(
&
x509_cred
);
if
(
ssl_cafile
)
{
rc
=
gnutls_certificate_set_x509_trust_file
(
x509_cred
,
ssl_cafile
,
GNUTLS_X509_FMT_PEM
);
if
(
rc
<
0
)
{
s
->
last_err
=
rc
;
return
-
1
;
}
}
gnutls_credentials_set
(
s
->
session
,
GNUTLS_CRD_CERTIFICATE
,
x509_cred
);
gnutls_transport_set_ptr2
(
s
->
session
,
(
gnutls_transport_ptr
)
s
->
ifd
,
(
gnutls_transport_ptr
)
s
->
ofd
);
return
0
;
}
static
int
_tls_open_client
(
stream_t
stream
)
{
struct
_tls_stream
*
s
=
stream_get_owner
(
stream
);
int
rc
=
0
;
switch
(
s
->
state
)
{
case
state_closed
:
gnutls_certificate_free_credentials
(
x509_cred
);
if
(
s
->
session
)
gnutls_deinit
(
s
->
session
);
/* FALLTHROUGH */
case
state_init
:
prepare_client_session
(
s
);
rc
=
gnutls_handshake
(
s
->
session
);
if
(
rc
<
0
)
{
s
->
last_err
=
rc
;
gnutls_deinit
(
s
->
session
);
s
->
state
=
state_init
;
return
-
1
;
}
break
;
default:
return
-
1
;
}
/* FIXME: if (ssl_cafile) verify_certificate (s->session); */
s
->
state
=
state_open
;
return
0
;
}
int
_tls_strerror
(
stream_t
stream
,
char
**
pstr
)
{
...
...
@@ -367,12 +504,12 @@ _tls_strerror (stream_t stream, char **pstr)
return
0
;
}
/* FIXME: It returns only input fd */
int
_tls_get_fd
(
stream_t
stream
,
int
*
pfd
)
_tls_get_fd
(
stream_t
stream
,
int
*
pfd
1
,
int
*
pfd2
)
{
struct
_tls_stream
*
s
=
stream_get_owner
(
stream
);
*
pfd
=
s
->
ifd
;
*
pfd1
=
s
->
ifd
;
*
pfd2
=
s
->
ofd
;
return
0
;
}
...
...
@@ -408,11 +545,67 @@ tls_stream_create (stream_t *stream, int in_fd, int out_fd, int flags)
stream_set_destroy
(
*
stream
,
_tls_destroy
,
s
);
stream_set_strerror
(
*
stream
,
_tls_strerror
,
s
);
stream_set_fd
(
*
stream
,
_tls_get_fd
,
s
);
_auth_lb_create
(
&
s
->
lb
);
s
->
state
=
state_init
;
return
0
;
}
int
tls_stream_create_client
(
stream_t
*
stream
,
int
in_fd
,
int
out_fd
,
int
flags
)
{
struct
_tls_stream
*
s
;
int
rc
;
if
(
stream
==
NULL
)
return
EINVAL
;
s
=
calloc
(
1
,
sizeof
(
*
s
));
if
(
s
==
NULL
)
return
ENOMEM
;
s
->
ifd
=
in_fd
;
s
->
ofd
=
out_fd
;
rc
=
stream_create
(
stream
,
flags
|
MU_STREAM_NO_CHECK
,
s
);
if
(
rc
)
{
free
(
s
);
return
rc
;
}
stream_set_open
(
*
stream
,
_tls_open_client
,
s
);
stream_set_close
(
*
stream
,
_tls_close
,
s
);
stream_set_read
(
*
stream
,
_tls_read
,
s
);
stream_set_readline
(
*
stream
,
_tls_readline
,
s
);
stream_set_write
(
*
stream
,
_tls_write
,
s
);
stream_set_flush
(
*
stream
,
_tls_flush
,
s
);
stream_set_destroy
(
*
stream
,
_tls_destroy
,
s
);
stream_set_strerror
(
*
stream
,
_tls_strerror
,
s
);
stream_set_fd
(
*
stream
,
_tls_get_fd
,
s
);
_auth_lb_create
(
&
s
->
lb
);
s
->
state
=
state_init
;
return
0
;
}
int
tls_stream_create_client_from_tcp
(
stream_t
*
stream
,
stream_t
tcp_str
,
int
flags
)
{
int
rc
,
fd
;
stream_get_fd
(
tcp_str
,
&
fd
);
rc
=
tls_stream_create_client
(
stream
,
fd
,
fd
,
flags
);
if
(
rc
==
0
)
{
struct
_tls_stream
*
s
=
stream_get_owner
(
*
stream
);
s
->
tcp_str
=
tcp_str
;
}
return
rc
;
}
#endif
/* WITH_TLS */
/* EOF */
...
...
Please
register
or
sign in
to post a comment