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