This source file includes following definitions.
- debug_log
- remoted__read_handshake_data
- lrmd_remote_client_msg
- lrmd_remote_client_destroy
- lrmd_auth_timeout_cb
- lrmd_remote_listen
- tls_server_dropped
- lrmd_tls_server_key_cb
- bind_and_listen
- get_address_info
- lrmd_init_remote_tls_server
- execd_stop_tls_server
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <glib.h>
13 #include <unistd.h>
14
15 #include <crm/crm.h>
16 #include <crm/common/mainloop.h>
17 #include <crm/common/xml.h>
18 #include <crm/common/remote_internal.h>
19 #include <crm/lrmd_internal.h>
20
21 #include <netdb.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <netinet/ip.h>
25 #include <arpa/inet.h>
26
27 #include "pacemaker-execd.h"
28
29 #ifdef HAVE_GNUTLS_GNUTLS_H
30
31 # include <gnutls/gnutls.h>
32
33 # define LRMD_REMOTE_AUTH_TIMEOUT 10000
34 gnutls_psk_server_credentials_t psk_cred_s;
35 gnutls_dh_params_t dh_params;
36 static int ssock = -1;
37 extern int lrmd_call_id;
38
39 static void
40 debug_log(int level, const char *str)
41 {
42 fputs(str, stderr);
43 }
44
45
46
47
48
49
50
51
52
53 static int
54 remoted__read_handshake_data(pcmk__client_t *client)
55 {
56 int rc = pcmk__read_handshake_data(client);
57
58 if (rc == EAGAIN) {
59
60
61
62 return 0;
63 } else if (rc != pcmk_rc_ok) {
64 return -1;
65 }
66
67 if (client->remote->auth_timeout) {
68 g_source_remove(client->remote->auth_timeout);
69 }
70 client->remote->auth_timeout = 0;
71
72 pcmk__set_client_flags(client, pcmk__client_tls_handshake_complete);
73 crm_notice("Remote client connection accepted");
74
75
76
77
78 pcmk__set_client_flags(client, pcmk__client_privileged);
79
80
81 notify_of_new_client(client);
82 return 0;
83 }
84
85 static int
86 lrmd_remote_client_msg(gpointer data)
87 {
88 int id = 0;
89 int rc;
90 xmlNode *request = NULL;
91 pcmk__client_t *client = data;
92
93 if (!pcmk_is_set(client->flags,
94 pcmk__client_tls_handshake_complete)) {
95 return remoted__read_handshake_data(client);
96 }
97
98 switch (pcmk__remote_ready(client->remote, 0)) {
99 case pcmk_rc_ok:
100 break;
101 case ETIME:
102 return 0;
103 default:
104 crm_info("Remote client disconnected while polling it");
105 return -1;
106 }
107
108 rc = pcmk__read_remote_message(client->remote, -1);
109
110 request = pcmk__remote_message_xml(client->remote);
111 while (request) {
112 crm_element_value_int(request, PCMK__XA_LRMD_REMOTE_MSG_ID, &id);
113 crm_trace("Processing remote client request %d", id);
114 if (!client->name) {
115 client->name = crm_element_value_copy(request,
116 PCMK__XA_LRMD_CLIENTNAME);
117 }
118
119 lrmd_call_id++;
120 if (lrmd_call_id < 1) {
121 lrmd_call_id = 1;
122 }
123
124 crm_xml_add(request, PCMK__XA_LRMD_CLIENTID, client->id);
125 crm_xml_add(request, PCMK__XA_LRMD_CLIENTNAME, client->name);
126 crm_xml_add_int(request, PCMK__XA_LRMD_CALLID, lrmd_call_id);
127
128 process_lrmd_message(client, id, request);
129 free_xml(request);
130
131
132 request = pcmk__remote_message_xml(client->remote);
133 }
134
135 if (rc == ENOTCONN) {
136 crm_info("Remote client disconnected while reading from it");
137 return -1;
138 }
139
140 return 0;
141 }
142
143 static void
144 lrmd_remote_client_destroy(gpointer user_data)
145 {
146 pcmk__client_t *client = user_data;
147
148 if (client == NULL) {
149 return;
150 }
151
152 crm_notice("Cleaning up after remote client %s disconnected",
153 pcmk__client_name(client));
154
155 ipc_proxy_remove_provider(client);
156
157
158
159 if (pcmk__ipc_client_count() == 1) {
160 client_disconnect_cleanup(NULL);
161 }
162
163 if (client->remote->tls_session) {
164 void *sock_ptr;
165 int csock;
166
167 sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session);
168 csock = GPOINTER_TO_INT(sock_ptr);
169
170 gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_RDWR);
171 gnutls_deinit(*client->remote->tls_session);
172 gnutls_free(client->remote->tls_session);
173 client->remote->tls_session = NULL;
174 close(csock);
175 }
176
177 lrmd_client_destroy(client);
178 return;
179 }
180
181 static gboolean
182 lrmd_auth_timeout_cb(gpointer data)
183 {
184 pcmk__client_t *client = data;
185
186 client->remote->auth_timeout = 0;
187
188 if (pcmk_is_set(client->flags,
189 pcmk__client_tls_handshake_complete)) {
190 return FALSE;
191 }
192
193 mainloop_del_fd(client->remote->source);
194 client->remote->source = NULL;
195 crm_err("Remote client authentication timed out");
196
197 return FALSE;
198 }
199
200
201 static int
202 lrmd_remote_listen(gpointer data)
203 {
204 int csock = -1;
205 gnutls_session_t *session = NULL;
206 pcmk__client_t *new_client = NULL;
207
208
209 static struct mainloop_fd_callbacks lrmd_remote_fd_cb = {
210 .dispatch = lrmd_remote_client_msg,
211 .destroy = lrmd_remote_client_destroy,
212 };
213
214 CRM_CHECK(ssock >= 0, return TRUE);
215
216 if (pcmk__accept_remote_connection(ssock, &csock) != pcmk_rc_ok) {
217 return TRUE;
218 }
219
220 session = pcmk__new_tls_session(csock, GNUTLS_SERVER, GNUTLS_CRD_PSK,
221 psk_cred_s);
222 if (session == NULL) {
223 close(csock);
224 return TRUE;
225 }
226
227 new_client = pcmk__new_unauth_client(NULL);
228 new_client->remote = pcmk__assert_alloc(1, sizeof(pcmk__remote_t));
229 pcmk__set_client_flags(new_client, pcmk__client_tls);
230 new_client->remote->tls_session = session;
231
232
233 new_client->remote->auth_timeout = g_timeout_add(LRMD_REMOTE_AUTH_TIMEOUT,
234 lrmd_auth_timeout_cb,
235 new_client);
236 crm_info("Remote client pending authentication "
237 CRM_XS " %p id: %s", new_client, new_client->id);
238
239 new_client->remote->source =
240 mainloop_add_fd("pacemaker-remote-client", G_PRIORITY_DEFAULT, csock,
241 new_client, &lrmd_remote_fd_cb);
242 return TRUE;
243 }
244
245 static void
246 tls_server_dropped(gpointer user_data)
247 {
248 crm_notice("TLS server session ended");
249 return;
250 }
251
252
253 static int
254 lrmd_tls_server_key_cb(gnutls_session_t session, const char *username, gnutls_datum_t * key)
255 {
256 return (lrmd__init_remote_key(key) == pcmk_rc_ok)? 0 : -1;
257 }
258
259 static int
260 bind_and_listen(struct addrinfo *addr)
261 {
262 int optval;
263 int fd;
264 int rc;
265 char buffer[INET6_ADDRSTRLEN] = { 0, };
266
267 pcmk__sockaddr2str(addr->ai_addr, buffer);
268 crm_trace("Attempting to bind to address %s", buffer);
269
270 fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
271 if (fd < 0) {
272 rc = errno;
273 crm_err("Listener socket creation failed: %", pcmk_rc_str(rc));
274 return -rc;
275 }
276
277
278 optval = 1;
279 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
280 if (rc < 0) {
281 rc = errno;
282 crm_err("Local address reuse not allowed on %s: %s", buffer, pcmk_rc_str(rc));
283 close(fd);
284 return -rc;
285 }
286
287 if (addr->ai_family == AF_INET6) {
288 optval = 0;
289 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
290 if (rc < 0) {
291 rc = errno;
292 crm_err("Couldn't disable IPV6-only on %s: %s", buffer, pcmk_rc_str(rc));
293 close(fd);
294 return -rc;
295 }
296 }
297
298 if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
299 rc = errno;
300 crm_err("Cannot bind to %s: %s", buffer, pcmk_rc_str(rc));
301 close(fd);
302 return -rc;
303 }
304
305 if (listen(fd, 10) == -1) {
306 rc = errno;
307 crm_err("Cannot listen on %s: %s", buffer, pcmk_rc_str(rc));
308 close(fd);
309 return -rc;
310 }
311 return fd;
312 }
313
314 static int
315 get_address_info(const char *bind_name, int port, struct addrinfo **res)
316 {
317 int rc;
318 char port_str[6];
319 struct addrinfo hints;
320
321 memset(&hints, 0, sizeof(struct addrinfo));
322 hints.ai_flags = AI_PASSIVE;
323 hints.ai_family = AF_UNSPEC;
324 hints.ai_socktype = SOCK_STREAM;
325 hints.ai_protocol = IPPROTO_TCP;
326
327 snprintf(port_str, sizeof(port_str), "%d", port);
328 rc = getaddrinfo(bind_name, port_str, &hints, res);
329 rc = pcmk__gaierror2rc(rc);
330
331 if (rc != pcmk_rc_ok) {
332 crm_err("Unable to get IP address(es) for %s: %s",
333 (bind_name? bind_name : "local node"), pcmk_rc_str(rc));
334 return rc;
335 }
336
337 return pcmk_rc_ok;
338 }
339
340 int
341 lrmd_init_remote_tls_server(void)
342 {
343 int filter;
344 int port = crm_default_remote_port();
345 struct addrinfo *res = NULL, *iter;
346 gnutls_datum_t psk_key = { NULL, 0 };
347 const char *bind_name = pcmk__env_option(PCMK__ENV_REMOTE_ADDRESS);
348
349 static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
350 .dispatch = lrmd_remote_listen,
351 .destroy = tls_server_dropped,
352 };
353
354 CRM_CHECK(ssock == -1, return ssock);
355
356 crm_debug("Starting TLS listener on %s port %d",
357 (bind_name? bind_name : "all addresses on"), port);
358 crm_gnutls_global_init();
359 gnutls_global_set_log_function(debug_log);
360
361 if (pcmk__init_tls_dh(&dh_params) != pcmk_rc_ok) {
362 return -1;
363 }
364 gnutls_psk_allocate_server_credentials(&psk_cred_s);
365 gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb);
366 gnutls_psk_set_server_dh_params(psk_cred_s, dh_params);
367
368
369
370
371
372
373 if (lrmd__init_remote_key(&psk_key) != pcmk_rc_ok) {
374 crm_warn("A cluster connection will not be possible until the key is available");
375 }
376 gnutls_free(psk_key.data);
377
378 if (get_address_info(bind_name, port, &res) != pcmk_rc_ok) {
379 return -1;
380 }
381
382
383
384
385
386
387
388
389
390
391
392 iter = res;
393 filter = AF_INET6;
394 while (iter) {
395 if (iter->ai_family == filter) {
396 ssock = bind_and_listen(iter);
397 }
398 if (ssock >= 0) {
399 break;
400 }
401
402 iter = iter->ai_next;
403 if (iter == NULL && filter == AF_INET6) {
404 iter = res;
405 filter = AF_INET;
406 }
407 }
408
409 if (ssock >= 0) {
410 mainloop_add_fd("pacemaker-remote-server", G_PRIORITY_DEFAULT, ssock,
411 NULL, &remote_listen_fd_callbacks);
412 crm_debug("Started TLS listener on %s port %d",
413 (bind_name? bind_name : "all addresses on"), port);
414 }
415 freeaddrinfo(res);
416 return ssock;
417 }
418
419 void
420 execd_stop_tls_server(void)
421 {
422 if (psk_cred_s) {
423 gnutls_psk_free_server_credentials(psk_cred_s);
424 psk_cred_s = 0;
425 }
426
427 if (ssock >= 0) {
428 close(ssock);
429 ssock = -1;
430 }
431 }
432 #endif