PageRenderTime 105ms CodeModel.GetById 52ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 0ms

/src/libmanos/manos_tls.c

http://github.com/jacksonh/manos
C | 298 lines | 230 code | 68 blank | 0 comment | 50 complexity | 3a0857615db16b39ffa4b77a0dabc081 MD5 | raw file
  1#include "config.h"
  2
  3#ifdef false && HAVE_LIBGNUTLS
  4
  5
  6#include <stdlib.h>
  7#include <stdio.h>
  8#include <unistd.h>
  9#include <fcntl.h>
 10#include <errno.h>
 11#include <string.h>
 12
 13#include <sys/ioctl.h>
 14#include <sys/socket.h>
 15#include <sys/un.h>
 16#include <sys/types.h>
 17
 18#include <arpa/inet.h>
 19
 20#include <netdb.h>
 21#include <netinet/in.h>
 22#include <netinet/tcp.h>
 23
 24#include <gnutls/gnutls.h>
 25
 26#include "manos.h"
 27
 28
 29gnutls_priority_t	priority_cache;
 30gnutls_dh_params_t	dh_params;
 31
 32
 33static int
 34get_dh_params (gnutls_session_t session, gnutls_params_type_t type, gnutls_params_st *res)
 35{
 36	if (type != GNUTLS_PARAMS_DH) {
 37		return -1;
 38	}
 39
 40	res->type = type;
 41	res->deinit = 0;
 42	res->params.dh = dh_params;
 43
 44	return 0;
 45}
 46
 47
 48int
 49manos_tls_global_init (const char *priorities)
 50{
 51	int err;
 52
 53	priority_cache = NULL;
 54	dh_params = NULL;
 55   
 56	err = gnutls_global_init ();
 57	if (err != 0) {
 58		return -1;
 59	}
 60
 61	err = gnutls_priority_init (&priority_cache, priorities, NULL);
 62	if (err != 0) {
 63		return -2;
 64	}
 65
 66	return 0;
 67}
 68
 69void
 70manos_tls_global_end ()
 71{
 72	gnutls_priority_deinit (priority_cache);
 73	gnutls_dh_params_deinit (dh_params);
 74	gnutls_global_deinit ();
 75}
 76
 77int
 78manos_tls_regenerate_dhparams (int bits)
 79{
 80	gnutls_dh_params_t params, oldparams;
 81	int err;
 82
 83	err = gnutls_dh_params_init (&params);
 84	if (err != 0) {
 85		return err;
 86	}
 87
 88	err = gnutls_dh_params_generate2 (params, bits);
 89	if (err != 0) {
 90		gnutls_dh_params_deinit (params);
 91		return err;
 92	}
 93
 94	oldparams = dh_params;
 95	dh_params = params;
 96
 97	if (oldparams != NULL) {
 98		gnutls_dh_params_deinit (oldparams);
 99	}
100
101	return 0;
102}
103
104int
105manos_tls_init (manos_tls_socket_t *tls, const char *cert, const char *key)
106{
107	manos_tls_socket_t socket;
108	int err;
109
110	socket = malloc (sizeof (*socket));
111	if (socket == NULL) {
112		return ENOMEM;
113	}
114
115	memset (socket, 0, sizeof (*socket));
116
117	err = gnutls_certificate_allocate_credentials (&socket->credentials);
118	if (err != 0) {
119		return err;
120	}
121
122	err = gnutls_certificate_set_x509_key_file (socket->credentials, cert, key, GNUTLS_X509_FMT_PEM);
123	if (err != 0) {
124		return err;
125	}
126
127	gnutls_certificate_set_params_function(socket->credentials, get_dh_params);
128
129	*tls = socket;
130	return 0;
131}
132
133int
134manos_tls_listen (manos_tls_socket_t tls, const char *host, int port, int backlog, int *reserr)
135{
136	int err;
137
138	*reserr = 0;
139	tls->socket = manos_socket_listen (host, port, backlog, &err);
140	if (tls->socket == -1) {
141		*reserr = err;
142		return -1;
143	}
144
145	return tls->socket;
146}
147
148static int
149do_handshake (manos_tls_socket_t tls)
150{
151	int err;
152
153	if (tls->handshake_done) {
154		return 0;
155	}
156
157	err = gnutls_handshake (tls->tls_session);
158	if (err != 0) {
159		return err;
160	} else {
161		tls->handshake_done = 1;
162		return 0;
163	}
164}
165
166int
167manos_tls_accept (manos_tls_socket_t server, manos_tls_socket_t *client, manos_socket_info_t *info)
168{
169	int err, inner_err;
170	manos_tls_socket_t client_socket;
171	
172	err = manos_socket_accept (server->socket, info, &inner_err);
173	if (err < 0) {
174		if (inner_err == 0) {
175			return EAGAIN;
176		} else {
177			return inner_err;
178		}
179	}
180
181	client_socket = malloc (sizeof (*client_socket));
182	if (client_socket == NULL) {
183		close (info->fd);
184		return ENOMEM;
185	}
186
187	memset (client_socket, 0, sizeof (*client_socket));
188
189	client_socket->socket = info->fd;
190
191	err = gnutls_init (&(client_socket->tls_session), GNUTLS_SERVER);
192	if (err != 0) {
193		close (info->fd);
194		if (err != GNUTLS_E_MEMORY_ERROR) {
195			gnutls_deinit (client_socket->tls_session);
196		} else {
197			err = ENOMEM;
198		}
199		free (client_socket);
200		return err;
201	}
202
203	gnutls_priority_set (client_socket->tls_session, priority_cache);
204	gnutls_credentials_set (client_socket->tls_session, GNUTLS_CRD_CERTIFICATE, server->credentials);
205	gnutls_transport_set_ptr (client_socket->tls_session, (gnutls_transport_ptr_t) info->fd);
206
207	*client = client_socket;
208	do_handshake(client_socket);
209
210	return 0;
211}
212
213static int
214tls_errno_or_again (int tlserror)
215{
216	if (tlserror == GNUTLS_E_AGAIN || tlserror == GNUTLS_E_INTERRUPTED) {
217		return 0;
218	} else {
219		return tlserror;
220	}
221}
222
223int
224manos_tls_receive (manos_tls_socket_t tls, char *data, int len, int *reserr)
225{
226	int recvd, err;
227
228	*reserr = 0;
229
230	err = do_handshake (tls);
231	if (err != 0) {
232		*reserr = tls_errno_or_again (err);
233		return -1;
234	}
235
236	recvd = gnutls_record_recv (tls->tls_session, data, len);
237	if (recvd < 0) {
238		*reserr = tls_errno_or_again (recvd);
239		return -1;
240	}
241
242	return recvd;
243}
244
245int
246manos_tls_send (manos_tls_socket_t tls, const char *data, int offset, int len, int *reserr)
247{
248	int sent, err;
249
250	*reserr = 0;
251
252	err = do_handshake (tls);
253	if (err != 0) {
254		*reserr = tls_errno_or_again (err);
255		return -1;
256	}
257
258	sent = gnutls_record_send (tls->tls_session, data + offset, len);
259	if (sent < 0) {
260		*reserr = tls_errno_or_again (sent);
261		return -1;
262	}
263
264	return sent;
265}
266
267int
268manos_tls_redo_handshake (manos_tls_socket_t tls)
269{
270	int err;
271
272	err = gnutls_rehandshake (tls->tls_session);
273	if (err != 0) {
274		return err;
275	}
276
277	tls->handshake_done = 0;
278	return 0;
279}
280
281int
282manos_tls_close (manos_tls_socket_t tls)
283{
284	int err;
285
286	err = gnutls_bye (tls->tls_session, GNUTLS_SHUT_RDWR);
287	close (tls->socket);
288	if (tls->credentials) {
289		gnutls_certificate_free_credentials (tls->credentials);
290	}
291	gnutls_deinit (tls->tls_session);
292	free (tls);
293
294	return 0;
295}
296
297
298#endif