123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /*
- * Copyright (C) 2012 Martin Willi
- * Copyright (C) 2012 revosec AG
- *
- * This program 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 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program 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.
- */
- #include "pt_tls_dispatcher.h"
- #include "pt_tls_server.h"
- #include <threading/thread.h>
- #include <utils/debug.h>
- #include <processing/jobs/callback_job.h>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h>
- typedef struct private_pt_tls_dispatcher_t private_pt_tls_dispatcher_t;
- /**
- * Private data of an pt_tls_dispatcher_t object.
- */
- struct private_pt_tls_dispatcher_t {
- /**
- * Public pt_tls_dispatcher_t interface.
- */
- pt_tls_dispatcher_t public;
- /**
- * Listening socket
- */
- int fd;
- /**
- * Client authentication requirements
- */
- pt_tls_auth_t auth;
- /**
- * Server identity
- */
- identification_t *server;
- /**
- * Peer identity
- */
- identification_t *peer;
- /**
- * TNCCS protocol handler constructor
- */
- pt_tls_tnccs_constructor_t *create;
- };
- /**
- * Open listening server socket
- */
- static bool open_socket(private_pt_tls_dispatcher_t *this, host_t *host)
- {
- this->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (this->fd == -1)
- {
- DBG1(DBG_TNC, "opening PT-TLS socket failed: %s", strerror(errno));
- return FALSE;
- }
- if (bind(this->fd, host->get_sockaddr(host),
- *host->get_sockaddr_len(host)) == -1)
- {
- DBG1(DBG_TNC, "binding to PT-TLS socket failed: %s", strerror(errno));
- return FALSE;
- }
- if (listen(this->fd, 5) == -1)
- {
- DBG1(DBG_TNC, "listen on PT-TLS socket failed: %s", strerror(errno));
- return FALSE;
- }
- return TRUE;
- }
- /**
- * Handle a single PT-TLS client connection
- */
- static job_requeue_t handle(pt_tls_server_t *connection)
- {
- while (TRUE)
- {
- switch (connection->handle(connection))
- {
- case NEED_MORE:
- continue;
- case FAILED:
- case SUCCESS:
- default:
- break;
- }
- break;
- }
- return JOB_REQUEUE_NONE;
- }
- /**
- * Clean up connection state
- */
- static void cleanup(pt_tls_server_t *connection)
- {
- int fd;
- fd = connection->get_fd(connection);
- connection->destroy(connection);
- close(fd);
- }
- METHOD(pt_tls_dispatcher_t, dispatch, void,
- private_pt_tls_dispatcher_t *this,
- pt_tls_tnccs_constructor_t *create)
- {
- while (TRUE)
- {
- pt_tls_server_t *connection;
- tnccs_t *tnccs;
- bool old;
- int fd;
- old = thread_cancelability(TRUE);
- fd = accept(this->fd, NULL, NULL);
- thread_cancelability(old);
- if (fd == -1)
- {
- DBG1(DBG_TNC, "accepting PT-TLS failed: %s", strerror(errno));
- continue;
- }
- tnccs = create(this->server, this->peer);
- if (!tnccs)
- {
- close(fd);
- continue;
- }
- connection = pt_tls_server_create(this->server, fd, this->auth, tnccs);
- if (!connection)
- {
- close(fd);
- continue;
- }
- lib->processor->queue_job(lib->processor,
- (job_t*)callback_job_create_with_prio((callback_job_cb_t)handle,
- connection, (void*)cleanup,
- (callback_job_cancel_t)return_false,
- JOB_PRIO_CRITICAL));
- }
- }
- METHOD(pt_tls_dispatcher_t, destroy, void,
- private_pt_tls_dispatcher_t *this)
- {
- if (this->fd != -1)
- {
- close(this->fd);
- }
- this->server->destroy(this->server);
- this->peer->destroy(this->peer);
- free(this);
- }
- /**
- * See header
- */
- pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
- identification_t *id, pt_tls_auth_t auth)
- {
- private_pt_tls_dispatcher_t *this;
- INIT(this,
- .public = {
- .dispatch = _dispatch,
- .destroy = _destroy,
- },
- .server = id->clone(id),
- /* we currently don't authenticate the peer, use %any identity */
- .peer = identification_create_from_encoding(ID_ANY, chunk_empty),
- .fd = -1,
- .auth = auth,
- );
- if (!open_socket(this, address))
- {
- destroy(this);
- return NULL;
- }
- return &this->public;
- }
|