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