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
- lrmd_remote_connection_destroy
- lrmd_tls_server_key_cb
- bind_and_listen
- get_address_info
- lrmd_init_remote_tls_server
- lrmd_tls_server_destroy
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 static int
52 remoted__read_handshake_data(pcmk__client_t *client)
53 {
54 int rc = pcmk__read_handshake_data(client);
55
56 if (rc == EAGAIN) {
57
58
59
60 return 0;
61 } else if (rc != pcmk_rc_ok) {
62 return -1;
63 }
64
65 if (client->remote->auth_timeout) {
66 g_source_remove(client->remote->auth_timeout);
67 }
68 client->remote->auth_timeout = 0;
69
70 client->remote->tls_handshake_complete = TRUE;
71 crm_notice("Remote client connection accepted");
72
73
74
75
76 pcmk__set_client_flags(client, pcmk__client_privileged);
77
78
79 notify_of_new_client(client);
80 return 0;
81 }
82
83 static int
84 lrmd_remote_client_msg(gpointer data)
85 {
86 int id = 0;
87 int rc;
88 xmlNode *request = NULL;
89 pcmk__client_t *client = data;
90
91 if (client->remote->tls_handshake_complete == FALSE) {
92 return remoted__read_handshake_data(client);
93 }
94
95 switch (pcmk__remote_ready(client->remote, 0)) {
96 case pcmk_rc_ok:
97 break;
98 case ETIME:
99 return 0;
100 default:
101 crm_info("Remote client disconnected while polling it");
102 return -1;
103 }
104
105 rc = pcmk__read_remote_message(client->remote, -1);
106
107 request = pcmk__remote_message_xml(client->remote);
108 while (request) {
109 crm_element_value_int(request, F_LRMD_REMOTE_MSG_ID, &id);
110 crm_trace("Processing remote client request %d", id);
111 if (!client->name) {
112 const char *value = crm_element_value(request, F_LRMD_CLIENTNAME);
113
114 if (value) {
115 client->name = strdup(value);
116 }
117 }
118
119 lrmd_call_id++;
120 if (lrmd_call_id < 1) {
121 lrmd_call_id = 1;
122 }
123
124 crm_xml_add(request, F_LRMD_CLIENTID, client->id);
125 crm_xml_add(request, F_LRMD_CLIENTNAME, client->name);
126 crm_xml_add_int(request, F_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 close(csock);
174 }
175
176 lrmd_client_destroy(client);
177 return;
178 }
179
180 static gboolean
181 lrmd_auth_timeout_cb(gpointer data)
182 {
183 pcmk__client_t *client = data;
184
185 client->remote->auth_timeout = 0;
186
187 if (client->remote->tls_handshake_complete == TRUE) {
188 return FALSE;
189 }
190
191 mainloop_del_fd(client->remote->source);
192 client->remote->source = NULL;
193 crm_err("Remote client authentication timed out");
194
195 return FALSE;
196 }
197
198
199 static int
200 lrmd_remote_listen(gpointer data)
201 {
202 int csock = -1;
203 gnutls_session_t *session = NULL;
204 pcmk__client_t *new_client = NULL;
205
206
207 static struct mainloop_fd_callbacks lrmd_remote_fd_cb = {
208 .dispatch = lrmd_remote_client_msg,
209 .destroy = lrmd_remote_client_destroy,
210 };
211
212 CRM_CHECK(ssock >= 0, return TRUE);
213
214 if (pcmk__accept_remote_connection(ssock, &csock) != pcmk_rc_ok) {
215 return TRUE;
216 }
217
218 session = pcmk__new_tls_session(csock, GNUTLS_SERVER, GNUTLS_CRD_PSK,
219 psk_cred_s);
220 if (session == NULL) {
221 close(csock);
222 return TRUE;
223 }
224
225 new_client = pcmk__new_unauth_client(NULL);
226 new_client->remote = calloc(1, sizeof(pcmk__remote_t));
227 pcmk__set_client_flags(new_client, pcmk__client_tls);
228 new_client->remote->tls_session = session;
229
230
231 new_client->remote->auth_timeout = g_timeout_add(LRMD_REMOTE_AUTH_TIMEOUT,
232 lrmd_auth_timeout_cb,
233 new_client);
234 crm_info("Remote client pending authentication "
235 CRM_XS " %p id: %s", new_client, new_client->id);
236
237 new_client->remote->source =
238 mainloop_add_fd("pacemaker-remote-client", G_PRIORITY_DEFAULT, csock,
239 new_client, &lrmd_remote_fd_cb);
240 return TRUE;
241 }
242
243 static void
244 lrmd_remote_connection_destroy(gpointer user_data)
245 {
246 crm_notice("TLS server session ended");
247 return;
248 }
249
250
251 static int
252 lrmd_tls_server_key_cb(gnutls_session_t session, const char *username, gnutls_datum_t * key)
253 {
254 return (lrmd__init_remote_key(key) == pcmk_rc_ok)? 0 : -1;
255 }
256
257 static int
258 bind_and_listen(struct addrinfo *addr)
259 {
260 int optval;
261 int fd;
262 int rc;
263 char buffer[INET6_ADDRSTRLEN] = { 0, };
264
265 pcmk__sockaddr2str(addr->ai_addr, buffer);
266 crm_trace("Attempting to bind to address %s", buffer);
267
268 fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
269 if (fd < 0) {
270 crm_perror(LOG_ERR, "Listener socket creation failed");
271 return -1;
272 }
273
274
275 optval = 1;
276 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
277 if (rc < 0) {
278 crm_perror(LOG_ERR, "Local address reuse not allowed on %s", buffer);
279 close(fd);
280 return -1;
281 }
282
283 if (addr->ai_family == AF_INET6) {
284 optval = 0;
285 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
286 if (rc < 0) {
287 crm_perror(LOG_INFO, "Couldn't disable IPV6-only on %s", buffer);
288 close(fd);
289 return -1;
290 }
291 }
292
293 if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
294 crm_perror(LOG_ERR, "Cannot bind to %s", buffer);
295 close(fd);
296 return -1;
297 }
298
299 if (listen(fd, 10) == -1) {
300 crm_perror(LOG_ERR, "Cannot listen on %s", buffer);
301 close(fd);
302 return -1;
303 }
304 return fd;
305 }
306
307 static int
308 get_address_info(const char *bind_name, int port, struct addrinfo **res)
309 {
310 int rc;
311 char port_str[6];
312 struct addrinfo hints;
313
314 memset(&hints, 0, sizeof(struct addrinfo));
315 hints.ai_flags = AI_PASSIVE;
316 hints.ai_family = AF_UNSPEC;
317 hints.ai_socktype = SOCK_STREAM;
318 hints.ai_protocol = IPPROTO_TCP;
319
320 snprintf(port_str, sizeof(port_str), "%d", port);
321 rc = getaddrinfo(bind_name, port_str, &hints, res);
322 if (rc) {
323 crm_err("Unable to get IP address(es) for %s: %s",
324 (bind_name? bind_name : "local node"), gai_strerror(rc));
325 return -EADDRNOTAVAIL;
326 }
327 return pcmk_ok;
328 }
329
330 int
331 lrmd_init_remote_tls_server()
332 {
333 int filter;
334 int port = crm_default_remote_port();
335 struct addrinfo *res = NULL, *iter;
336 gnutls_datum_t psk_key = { NULL, 0 };
337 const char *bind_name = getenv("PCMK_remote_address");
338
339 static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
340 .dispatch = lrmd_remote_listen,
341 .destroy = lrmd_remote_connection_destroy,
342 };
343
344 CRM_CHECK(ssock == -1, return ssock);
345
346 crm_debug("Starting TLS listener on %s port %d",
347 (bind_name? bind_name : "all addresses on"), port);
348 crm_gnutls_global_init();
349 gnutls_global_set_log_function(debug_log);
350
351 if (pcmk__init_tls_dh(&dh_params) != pcmk_rc_ok) {
352 return -1;
353 }
354 gnutls_psk_allocate_server_credentials(&psk_cred_s);
355 gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb);
356 gnutls_psk_set_server_dh_params(psk_cred_s, dh_params);
357
358
359
360
361
362
363 if (lrmd__init_remote_key(&psk_key) != pcmk_rc_ok) {
364 crm_warn("A cluster connection will not be possible until the key is available");
365 }
366 gnutls_free(psk_key.data);
367
368 if (get_address_info(bind_name, port, &res) != pcmk_ok) {
369 return -1;
370 }
371
372
373
374
375
376
377
378
379
380
381
382 iter = res;
383 filter = AF_INET6;
384 while (iter) {
385 if (iter->ai_family == filter) {
386 ssock = bind_and_listen(iter);
387 }
388 if (ssock != -1) {
389 break;
390 }
391
392 iter = iter->ai_next;
393 if (iter == NULL && filter == AF_INET6) {
394 iter = res;
395 filter = AF_INET;
396 }
397 }
398
399 if (ssock >= 0) {
400 mainloop_add_fd("pacemaker-remote-server", G_PRIORITY_DEFAULT, ssock,
401 NULL, &remote_listen_fd_callbacks);
402 crm_debug("Started TLS listener on %s port %d",
403 (bind_name? bind_name : "all addresses on"), port);
404 }
405 freeaddrinfo(res);
406 return ssock;
407 }
408
409 void
410 lrmd_tls_server_destroy(void)
411 {
412 if (psk_cred_s) {
413 gnutls_psk_free_server_credentials(psk_cred_s);
414 psk_cred_s = 0;
415 }
416
417 if (ssock >= 0) {
418 close(ssock);
419 ssock = -1;
420 }
421 }
422 #endif