Fixed some typos, courtesy of codespell
[strongswan.git] / src / libpttls / pt_tls_dispatcher.c
1 /*
2 * Copyright (C) 2012 Martin Willi
3 * Copyright (C) 2012 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "pt_tls_dispatcher.h"
17 #include "pt_tls_server.h"
18
19 #include <threading/thread.h>
20 #include <utils/debug.h>
21 #include <processing/jobs/callback_job.h>
22
23 #include <errno.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 typedef struct private_pt_tls_dispatcher_t private_pt_tls_dispatcher_t;
28
29 /**
30 * Private data of an pt_tls_dispatcher_t object.
31 */
32 struct private_pt_tls_dispatcher_t {
33
34 /**
35 * Public pt_tls_dispatcher_t interface.
36 */
37 pt_tls_dispatcher_t public;
38
39 /**
40 * Listening socket
41 */
42 int fd;
43
44 /**
45 * Client authentication requirements
46 */
47 pt_tls_auth_t auth;
48
49 /**
50 * Server identity
51 */
52 identification_t *server;
53
54 /**
55 * Peer identity
56 */
57 identification_t *peer;
58
59 /**
60 * TNCCS protocol handler constructor
61 */
62 pt_tls_tnccs_constructor_t *create;
63 };
64
65 /**
66 * Open listening server socket
67 */
68 static bool open_socket(private_pt_tls_dispatcher_t *this, host_t *host)
69 {
70 this->fd = socket(AF_INET, SOCK_STREAM, 0);
71 if (this->fd == -1)
72 {
73 DBG1(DBG_TNC, "opening PT-TLS socket failed: %s", strerror(errno));
74 return FALSE;
75 }
76 if (bind(this->fd, host->get_sockaddr(host),
77 *host->get_sockaddr_len(host)) == -1)
78 {
79 DBG1(DBG_TNC, "binding to PT-TLS socket failed: %s", strerror(errno));
80 return FALSE;
81 }
82 if (listen(this->fd, 5) == -1)
83 {
84 DBG1(DBG_TNC, "listen on PT-TLS socket failed: %s", strerror(errno));
85 return FALSE;
86 }
87 return TRUE;
88 }
89
90 /**
91 * Handle a single PT-TLS client connection
92 */
93 static job_requeue_t handle(pt_tls_server_t *connection)
94 {
95 while (TRUE)
96 {
97 switch (connection->handle(connection))
98 {
99 case NEED_MORE:
100 continue;
101 case FAILED:
102 case SUCCESS:
103 default:
104 break;
105 }
106 break;
107 }
108 return JOB_REQUEUE_NONE;
109 }
110
111 /**
112 * Clean up connection state
113 */
114 static void cleanup(pt_tls_server_t *connection)
115 {
116 int fd;
117
118 fd = connection->get_fd(connection);
119 connection->destroy(connection);
120 close(fd);
121 }
122
123 METHOD(pt_tls_dispatcher_t, dispatch, void,
124 private_pt_tls_dispatcher_t *this,
125 pt_tls_tnccs_constructor_t *create)
126 {
127 while (TRUE)
128 {
129 pt_tls_server_t *connection;
130 tnccs_t *tnccs;
131 bool old;
132 int fd;
133
134 old = thread_cancelability(TRUE);
135 fd = accept(this->fd, NULL, NULL);
136 thread_cancelability(old);
137 if (fd == -1)
138 {
139 DBG1(DBG_TNC, "accepting PT-TLS failed: %s", strerror(errno));
140 continue;
141 }
142
143 tnccs = create(this->server, this->peer);
144 if (!tnccs)
145 {
146 close(fd);
147 continue;
148 }
149 connection = pt_tls_server_create(this->server, fd, this->auth, tnccs);
150 if (!connection)
151 {
152 close(fd);
153 continue;
154 }
155 lib->processor->queue_job(lib->processor,
156 (job_t*)callback_job_create_with_prio((callback_job_cb_t)handle,
157 connection, (void*)cleanup,
158 (callback_job_cancel_t)return_false,
159 JOB_PRIO_CRITICAL));
160 }
161 }
162
163 METHOD(pt_tls_dispatcher_t, destroy, void,
164 private_pt_tls_dispatcher_t *this)
165 {
166 if (this->fd != -1)
167 {
168 close(this->fd);
169 }
170 this->server->destroy(this->server);
171 this->peer->destroy(this->peer);
172 free(this);
173 }
174
175 /**
176 * See header
177 */
178 pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
179 identification_t *id, pt_tls_auth_t auth)
180 {
181 private_pt_tls_dispatcher_t *this;
182
183 INIT(this,
184 .public = {
185 .dispatch = _dispatch,
186 .destroy = _destroy,
187 },
188 .server = id->clone(id),
189 /* we currently don't authenticate the peer, use %any identity */
190 .peer = identification_create_from_encoding(ID_ANY, chunk_empty),
191 .fd = -1,
192 .auth = auth,
193 );
194
195 if (!open_socket(this, address))
196 {
197 destroy(this);
198 return NULL;
199 }
200
201 return &this->public;
202 }