This source file includes following definitions.
- debug_log
- 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
- lrmd_init_remote_tls_server
- lrmd_tls_server_destroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <crm_internal.h>
21
22 #include <glib.h>
23 #include <unistd.h>
24
25 #include <crm/crm.h>
26 #include <crm/msg_xml.h>
27 #include <crm/crm.h>
28 #include <crm/msg_xml.h>
29 #include <crm/common/mainloop.h>
30
31 #include <lrmd_private.h>
32
33 #include <netdb.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <arpa/inet.h>
38
39 #ifdef HAVE_GNUTLS_GNUTLS_H
40 # define LRMD_REMOTE_AUTH_TIMEOUT 10000
41 gnutls_psk_server_credentials_t psk_cred_s;
42 gnutls_dh_params_t dh_params;
43 static int ssock = -1;
44 extern int lrmd_call_id;
45
46 static void
47 debug_log(int level, const char *str)
48 {
49 fputs(str, stderr);
50 }
51
52 static int
53 lrmd_remote_client_msg(gpointer data)
54 {
55 int id = 0;
56 int rc = 0;
57 int disconnected = 0;
58 xmlNode *request = NULL;
59 crm_client_t *client = data;
60
61 if (client->remote->tls_handshake_complete == FALSE) {
62 int rc = 0;
63
64
65
66 do {
67 rc = gnutls_handshake(*client->remote->tls_session);
68
69 if (rc < 0 && rc != GNUTLS_E_AGAIN) {
70 crm_err("Remote lrmd tls handshake failed");
71 return -1;
72 }
73 } while (rc == GNUTLS_E_INTERRUPTED);
74
75 if (rc == 0) {
76 crm_debug("Remote lrmd tls handshake completed");
77 client->remote->tls_handshake_complete = TRUE;
78 if (client->remote->auth_timeout) {
79 g_source_remove(client->remote->auth_timeout);
80 }
81 client->remote->auth_timeout = 0;
82
83
84 notify_of_new_client(client);
85 }
86 return 0;
87 }
88
89 rc = crm_remote_ready(client->remote, 0);
90 if (rc == 0) {
91
92 return 0;
93 } else if (rc < 0) {
94 crm_info("Client disconnected during remote client read");
95 return -1;
96 }
97
98 crm_remote_recv(client->remote, -1, &disconnected);
99
100 request = crm_remote_parse_buffer(client->remote);
101 while (request) {
102 crm_element_value_int(request, F_LRMD_REMOTE_MSG_ID, &id);
103 crm_trace("processing request from remote client with remote msg id %d", id);
104 if (!client->name) {
105 const char *value = crm_element_value(request, F_LRMD_CLIENTNAME);
106
107 if (value) {
108 client->name = strdup(value);
109 }
110 }
111
112 lrmd_call_id++;
113 if (lrmd_call_id < 1) {
114 lrmd_call_id = 1;
115 }
116
117 crm_xml_add(request, F_LRMD_CLIENTID, client->id);
118 crm_xml_add(request, F_LRMD_CLIENTNAME, client->name);
119 crm_xml_add_int(request, F_LRMD_CALLID, lrmd_call_id);
120
121 process_lrmd_message(client, id, request);
122 free_xml(request);
123
124
125 request = crm_remote_parse_buffer(client->remote);
126 }
127
128 if (disconnected) {
129 crm_info("Client disconnect detected in tls msg dispatcher.");
130 return -1;
131 }
132
133 return 0;
134 }
135
136 static void
137 lrmd_remote_client_destroy(gpointer user_data)
138 {
139 crm_client_t *client = user_data;
140
141 if (client == NULL) {
142 return;
143 }
144
145 ipc_proxy_remove_provider(client);
146
147
148
149 if (crm_hash_table_size(client_connections) == 1) {
150 client_disconnect_cleanup(NULL);
151 }
152
153 crm_notice("LRMD client disconnecting remote client - name: %s id: %s",
154 client->name ? client->name : "<unknown>", client->id);
155
156 if (client->remote->tls_session) {
157 void *sock_ptr;
158 int csock;
159
160 sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session);
161 csock = GPOINTER_TO_INT(sock_ptr);
162
163 gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_RDWR);
164 gnutls_deinit(*client->remote->tls_session);
165 gnutls_free(client->remote->tls_session);
166 close(csock);
167 }
168
169 lrmd_client_destroy(client);
170 return;
171 }
172
173 static gboolean
174 lrmd_auth_timeout_cb(gpointer data)
175 {
176 crm_client_t *client = data;
177
178 client->remote->auth_timeout = 0;
179
180 if (client->remote->tls_handshake_complete == TRUE) {
181 return FALSE;
182 }
183
184 mainloop_del_fd(client->remote->source);
185 client->remote->source = NULL;
186 crm_err("Remote client authentication timed out");
187
188 return FALSE;
189 }
190
191 static int
192 lrmd_remote_listen(gpointer data)
193 {
194 int csock = 0;
195 gnutls_session_t *session = NULL;
196 crm_client_t *new_client = NULL;
197
198 static struct mainloop_fd_callbacks lrmd_remote_fd_cb = {
199 .dispatch = lrmd_remote_client_msg,
200 .destroy = lrmd_remote_client_destroy,
201 };
202
203 csock = crm_remote_accept(ssock);
204 if (csock < 0) {
205 return TRUE;
206 }
207
208 session = create_psk_tls_session(csock, GNUTLS_SERVER, psk_cred_s);
209 if (session == NULL) {
210 crm_err("TLS session creation failed");
211 close(csock);
212 return TRUE;
213 }
214
215 new_client = crm_client_alloc(NULL);
216 new_client->remote = calloc(1, sizeof(crm_remote_t));
217 new_client->kind = CRM_CLIENT_TLS;
218 new_client->remote->tls_session = session;
219 new_client->remote->auth_timeout =
220 g_timeout_add(LRMD_REMOTE_AUTH_TIMEOUT, lrmd_auth_timeout_cb, new_client);
221 crm_notice("LRMD client connection established. %p id: %s", new_client, new_client->id);
222
223 new_client->remote->source =
224 mainloop_add_fd("lrmd-remote-client", G_PRIORITY_DEFAULT, csock, new_client,
225 &lrmd_remote_fd_cb);
226 return TRUE;
227 }
228
229 static void
230 lrmd_remote_connection_destroy(gpointer user_data)
231 {
232 crm_notice("Remote tls server disconnected");
233 return;
234 }
235
236 static int
237 lrmd_tls_server_key_cb(gnutls_session_t session, const char *username, gnutls_datum_t * key)
238 {
239 return lrmd_tls_set_key(key);
240 }
241
242 static int
243 bind_and_listen(struct addrinfo *addr)
244 {
245 int optval;
246 int fd;
247 int rc;
248 char buffer[INET6_ADDRSTRLEN] = { 0, };
249
250 crm_sockaddr2str(addr->ai_addr, buffer);
251 crm_trace("Attempting to bind on address %s", buffer);
252
253 fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
254 if (fd < 0) {
255 return -1;
256 }
257
258
259 optval = 1;
260 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
261 if (rc < 0) {
262 crm_perror(LOG_INFO, "Couldn't allow the reuse of local addresses by our remote listener, bind address %s", buffer);
263 close(fd);
264 return -1;
265 }
266
267 if (addr->ai_family == AF_INET6) {
268 optval = 0;
269 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
270 if (rc < 0) {
271 crm_perror(LOG_INFO, "Couldn't disable IPV6 only on address %s", buffer);
272 close(fd);
273 return -1;
274 }
275 }
276
277 if (bind(fd, addr->ai_addr, addr->ai_addrlen) != 0) {
278 close(fd);
279 return -1;
280 }
281
282 if (listen(fd, 10) == -1) {
283 crm_err("Can not start listen on address %s", buffer);
284 close(fd);
285 return -1;
286 }
287
288 crm_notice("Listening on address %s", buffer);
289
290 return fd;
291 }
292
293 int
294 lrmd_init_remote_tls_server()
295 {
296 int rc;
297 int filter;
298 int port = crm_default_remote_port();
299 struct addrinfo hints, *res = NULL, *iter;
300 char port_str[6];
301 gnutls_datum_t psk_key = { NULL, 0 };
302
303 static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
304 .dispatch = lrmd_remote_listen,
305 .destroy = lrmd_remote_connection_destroy,
306 };
307
308 crm_notice("Starting TLS listener on port %d", port);
309 crm_gnutls_global_init();
310 gnutls_global_set_log_function(debug_log);
311
312 gnutls_dh_params_init(&dh_params);
313 gnutls_dh_params_generate2(dh_params, 1024);
314 gnutls_psk_allocate_server_credentials(&psk_cred_s);
315 gnutls_psk_set_server_credentials_function(psk_cred_s, lrmd_tls_server_key_cb);
316 gnutls_psk_set_server_dh_params(psk_cred_s, dh_params);
317
318
319
320
321
322
323 rc = lrmd_tls_set_key(&psk_key);
324 if (rc != 0) {
325 crm_warn("A cluster connection will not be possible until the key is available");
326 }
327
328 memset(&hints, 0, sizeof(struct addrinfo));
329
330
331
332 hints.ai_flags = AI_PASSIVE;
333 hints.ai_family = AF_UNSPEC;
334 hints.ai_socktype = SOCK_STREAM;
335 hints.ai_protocol = IPPROTO_TCP;
336
337 snprintf(port_str, sizeof(port_str), "%d", port);
338 rc = getaddrinfo(NULL, port_str, &hints, &res);
339 if (rc) {
340 crm_err("Unable to get IP address info for local node: %s",
341 gai_strerror(rc));
342 return -1;
343 }
344
345 iter = res;
346 filter = AF_INET6;
347
348 while (iter) {
349 if (iter->ai_family == filter) {
350 ssock = bind_and_listen(iter);
351 }
352 if (ssock != -1) {
353 break;
354 }
355
356 iter = iter->ai_next;
357 if (iter == NULL && filter == AF_INET6) {
358 iter = res;
359 filter = AF_INET;
360 }
361 }
362
363 if (ssock < 0) {
364 crm_err("unable to bind to address");
365 goto init_remote_cleanup;
366 }
367
368 mainloop_add_fd("lrmd-remote", G_PRIORITY_DEFAULT, ssock, NULL, &remote_listen_fd_callbacks);
369
370 rc = ssock;
371 init_remote_cleanup:
372 if (rc < 0) {
373 close(ssock);
374 ssock = 0;
375 }
376 freeaddrinfo(res);
377 return rc;
378
379 }
380
381 void
382 lrmd_tls_server_destroy(void)
383 {
384 if (psk_cred_s) {
385 gnutls_psk_free_server_credentials(psk_cred_s);
386 psk_cred_s = 0;
387 }
388
389 if (ssock > 0) {
390 close(ssock);
391 ssock = 0;
392 }
393 }
394 #endif