pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
ipc.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 
12 #if defined(US_AUTH_PEERCRED_UCRED) || defined(US_AUTH_PEERCRED_SOCKPEERCRED)
13 # ifdef US_AUTH_PEERCRED_UCRED
14 # ifndef _GNU_SOURCE
15 # define _GNU_SOURCE
16 # endif
17 # endif
18 # include <sys/socket.h>
19 #elif defined(US_AUTH_GETPEERUCRED)
20 # include <ucred.h>
21 #endif
22 
23 #include <sys/param.h>
24 
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <grp.h>
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <bzlib.h>
34 
35 #include <crm/crm.h> /* indirectly: pcmk_err_generic */
36 #include <crm/msg_xml.h>
37 #include <crm/common/ipc.h>
38 #include <crm/common/ipcs.h>
39 
40 #include <crm/common/ipc_internal.h> /* PCMK__SPECIAL_PID* */
41 
42 #define PCMK_IPC_VERSION 1
43 
44 /* Evict clients whose event queue grows this large (by default) */
45 #define PCMK_IPC_DEFAULT_QUEUE_MAX 500
46 
47 struct crm_ipc_response_header {
48  struct qb_ipc_response_header qb;
49  uint32_t size_uncompressed;
50  uint32_t size_compressed;
52  uint8_t version; /* Protect against version changes for anyone that might bother to statically link us */
53 };
54 
55 static int hdr_offset = 0;
56 static unsigned int ipc_buffer_max = 0;
57 static unsigned int pick_ipc_buffer(unsigned int max);
58 
59 static inline void
60 crm_ipc_init(void)
61 {
62  if (hdr_offset == 0) {
63  hdr_offset = sizeof(struct crm_ipc_response_header);
64  }
65  if (ipc_buffer_max == 0) {
66  ipc_buffer_max = pick_ipc_buffer(0);
67  }
68 }
69 
70 unsigned int
72 {
73  return pick_ipc_buffer(0);
74 }
75 
76 static char *
77 generateReference(const char *custom1, const char *custom2)
78 {
79  static uint ref_counter = 0;
80  const char *local_cust1 = custom1;
81  const char *local_cust2 = custom2;
82  int reference_len = 4;
83  char *since_epoch = NULL;
84 
85  reference_len += 20; /* too big */
86  reference_len += 40; /* too big */
87 
88  if (local_cust1 == NULL) {
89  local_cust1 = "_empty_";
90  }
91  reference_len += strlen(local_cust1);
92 
93  if (local_cust2 == NULL) {
94  local_cust2 = "_empty_";
95  }
96  reference_len += strlen(local_cust2);
97 
98  since_epoch = calloc(1, reference_len);
99 
100  if (since_epoch != NULL) {
101  sprintf(since_epoch, "%s-%s-%lu-%u",
102  local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++);
103  }
104 
105  return since_epoch;
106 }
107 
108 xmlNode *
109 create_request_adv(const char *task, xmlNode * msg_data,
110  const char *host_to, const char *sys_to,
111  const char *sys_from, const char *uuid_from, const char *origin)
112 {
113  char *true_from = NULL;
114  xmlNode *request = NULL;
115  char *reference = generateReference(task, sys_from);
116 
117  if (uuid_from != NULL) {
118  true_from = generate_hash_key(sys_from, uuid_from);
119  } else if (sys_from != NULL) {
120  true_from = strdup(sys_from);
121  } else {
122  crm_err("No sys from specified");
123  }
124 
125  /* host_from will get set for us if necessary by CRMd when routed */
126  request = create_xml_node(NULL, __FUNCTION__);
127  crm_xml_add(request, F_CRM_ORIGIN, origin);
128  crm_xml_add(request, F_TYPE, T_CRM);
131  crm_xml_add(request, F_CRM_REFERENCE, reference);
132  crm_xml_add(request, F_CRM_TASK, task);
133  crm_xml_add(request, F_CRM_SYS_TO, sys_to);
134  crm_xml_add(request, F_CRM_SYS_FROM, true_from);
135 
136  /* HOSTTO will be ignored if it is to the DC anyway. */
137  if (host_to != NULL && strlen(host_to) > 0) {
138  crm_xml_add(request, F_CRM_HOST_TO, host_to);
139  }
140 
141  if (msg_data != NULL) {
142  add_message_xml(request, F_CRM_DATA, msg_data);
143  }
144  free(reference);
145  free(true_from);
146 
147  return request;
148 }
149 
150 /*
151  * This method adds a copy of xml_response_data
152  */
153 xmlNode *
154 create_reply_adv(xmlNode * original_request, xmlNode * xml_response_data, const char *origin)
155 {
156  xmlNode *reply = NULL;
157 
158  const char *host_from = crm_element_value(original_request, F_CRM_HOST_FROM);
159  const char *sys_from = crm_element_value(original_request, F_CRM_SYS_FROM);
160  const char *sys_to = crm_element_value(original_request, F_CRM_SYS_TO);
161  const char *type = crm_element_value(original_request, F_CRM_MSG_TYPE);
162  const char *operation = crm_element_value(original_request, F_CRM_TASK);
163  const char *crm_msg_reference = crm_element_value(original_request, F_CRM_REFERENCE);
164 
165  if (type == NULL) {
166  crm_err("Cannot create new_message, no message type in original message");
167  CRM_ASSERT(type != NULL);
168  return NULL;
169 #if 0
170  } else if (strcasecmp(XML_ATTR_REQUEST, type) != 0) {
171  crm_err("Cannot create new_message, original message was not a request");
172  return NULL;
173 #endif
174  }
175  reply = create_xml_node(NULL, __FUNCTION__);
176  if (reply == NULL) {
177  crm_err("Cannot create new_message, malloc failed");
178  return NULL;
179  }
180 
181  crm_xml_add(reply, F_CRM_ORIGIN, origin);
182  crm_xml_add(reply, F_TYPE, T_CRM);
185  crm_xml_add(reply, F_CRM_REFERENCE, crm_msg_reference);
186  crm_xml_add(reply, F_CRM_TASK, operation);
187 
188  /* since this is a reply, we reverse the from and to */
189  crm_xml_add(reply, F_CRM_SYS_TO, sys_from);
190  crm_xml_add(reply, F_CRM_SYS_FROM, sys_to);
191 
192  /* HOSTTO will be ignored if it is to the DC anyway. */
193  if (host_from != NULL && strlen(host_from) > 0) {
194  crm_xml_add(reply, F_CRM_HOST_TO, host_from);
195  }
196 
197  if (xml_response_data != NULL) {
198  add_message_xml(reply, F_CRM_DATA, xml_response_data);
199  }
200 
201  return reply;
202 }
203 
204 /* Libqb based IPC */
205 
206 /* Server... */
207 
208 GHashTable *client_connections = NULL;
209 
210 crm_client_t *
211 crm_client_get(qb_ipcs_connection_t * c)
212 {
213  if (client_connections) {
214  return g_hash_table_lookup(client_connections, c);
215  }
216 
217  crm_trace("No client found for %p", c);
218  return NULL;
219 }
220 
221 crm_client_t *
222 crm_client_get_by_id(const char *id)
223 {
224  gpointer key;
225  crm_client_t *client;
226  GHashTableIter iter;
227 
228  if (client_connections && id) {
229  g_hash_table_iter_init(&iter, client_connections);
230  while (g_hash_table_iter_next(&iter, &key, (gpointer *) & client)) {
231  if (strcmp(client->id, id) == 0) {
232  return client;
233  }
234  }
235  }
236 
237  crm_trace("No client found with id=%s", id);
238  return NULL;
239 }
240 
241 const char *
243 {
244  if (c == NULL) {
245  return "null";
246  } else if (c->name == NULL && c->id == NULL) {
247  return "unknown";
248  } else if (c->name == NULL) {
249  return c->id;
250  } else {
251  return c->name;
252  }
253 }
254 
255 void
257 {
258  if (client_connections == NULL) {
259  crm_trace("Creating client hash table");
260  client_connections = g_hash_table_new(g_direct_hash, g_direct_equal);
261  }
262 }
263 
264 void
266 {
267  if (client_connections != NULL) {
268  int active = g_hash_table_size(client_connections);
269 
270  if (active) {
271  crm_err("Exiting with %d active connections", active);
272  }
273  g_hash_table_destroy(client_connections); client_connections = NULL;
274  }
275 }
276 
277 void
278 crm_client_disconnect_all(qb_ipcs_service_t *service)
279 {
280  qb_ipcs_connection_t *c = NULL;
281 
282  if (service == NULL) {
283  return;
284  }
285 
286  c = qb_ipcs_connection_first_get(service);
287 
288  while (c != NULL) {
289  qb_ipcs_connection_t *last = c;
290 
291  c = qb_ipcs_connection_next_get(service, last);
292 
293  /* There really shouldn't be anyone connected at this point */
294  crm_notice("Disconnecting client %p, pid=%d...", last, crm_ipcs_client_pid(last));
295  qb_ipcs_disconnect(last);
296  qb_ipcs_connection_unref(last);
297  }
298 }
299 
310 static crm_client_t *
311 client_from_connection(qb_ipcs_connection_t *c, void *key, uid_t uid_client)
312 {
313  crm_client_t *client = calloc(1, sizeof(crm_client_t));
314 
315  if (client == NULL) {
316  crm_perror(LOG_ERR, "Allocating client");
317  return NULL;
318  }
319 
320  if (c) {
321 #if ENABLE_ACL
322  client->user = uid2username(uid_client);
323  if (client->user == NULL) {
324  client->user = strdup("#unprivileged");
325  CRM_CHECK(client->user != NULL, free(client); return NULL);
326  crm_err("Unable to enforce ACLs for user ID %d, assuming unprivileged",
327  uid_client);
328  }
329 #endif
330  client->ipcs = c;
331  client->kind = CRM_CLIENT_IPC;
332  client->pid = crm_ipcs_client_pid(c);
333  if (key == NULL) {
334  key = c;
335  }
336  }
337 
338  client->id = crm_generate_uuid();
339  if (client->id == NULL) {
340  crm_err("Could not generate UUID for client");
341  free(client->user);
342  free(client);
343  return NULL;
344  }
345  if (key == NULL) {
346  key = client->id;
347  }
348  g_hash_table_insert(client_connections, key, client);
349  return client;
350 }
351 
359 crm_client_t *
361 {
362  crm_client_t *client = client_from_connection(NULL, key, 0);
363 
364  CRM_ASSERT(client != NULL);
365  return client;
366 }
367 
368 crm_client_t *
369 crm_client_new(qb_ipcs_connection_t * c, uid_t uid_client, gid_t gid_client)
370 {
371  static gid_t uid_cluster = 0;
372  static gid_t gid_cluster = 0;
373 
374  crm_client_t *client = NULL;
375 
376  CRM_CHECK(c != NULL, return NULL);
377 
378  if (uid_cluster == 0) {
379  if (crm_user_lookup(CRM_DAEMON_USER, &uid_cluster, &gid_cluster) < 0) {
380  static bool need_log = TRUE;
381 
382  if (need_log) {
383  crm_warn("Could not find user and group IDs for user %s",
385  need_log = FALSE;
386  }
387  }
388  }
389 
390  if (uid_client != 0) {
391  crm_trace("Giving access to group %u", gid_cluster);
392  /* Passing -1 to chown(2) means don't change */
393  qb_ipcs_connection_auth_set(c, -1, gid_cluster, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
394  }
395 
396  crm_client_init();
397 
398  /* TODO: Do our own auth checking, return NULL if unauthorized */
399  client = client_from_connection(c, NULL, uid_client);
400  if (client == NULL) {
401  return NULL;
402  }
403 
404  if ((uid_client == 0) || (uid_client == uid_cluster)) {
405  /* Remember when a connection came from root or hacluster */
407  }
408 
409  crm_debug("Connecting %p for uid=%d gid=%d pid=%u id=%s", c, uid_client, gid_client, client->pid, client->id);
410 
411  return client;
412 }
413 
414 void
416 {
417  if (c == NULL) {
418  return;
419  }
420 
421  if (client_connections) {
422  if (c->ipcs) {
423  crm_trace("Destroying %p/%p (%d remaining)",
424  c, c->ipcs, crm_hash_table_size(client_connections) - 1);
425  g_hash_table_remove(client_connections, c->ipcs);
426 
427  } else {
428  crm_trace("Destroying remote connection %p (%d remaining)",
429  c, crm_hash_table_size(client_connections) - 1);
430  g_hash_table_remove(client_connections, c->id);
431  }
432  }
433 
434  if (c->event_timer) {
435  g_source_remove(c->event_timer);
436  }
437 
438  crm_debug("Destroying %d events", g_list_length(c->event_queue));
439  while (c->event_queue) {
440  struct iovec *event = c->event_queue->data;
441 
442  c->event_queue = g_list_remove(c->event_queue, event);
443  free(event[0].iov_base);
444  free(event[1].iov_base);
445  free(event);
446  }
447 
448  free(c->id);
449  free(c->name);
450  free(c->user);
451  if (c->remote) {
452  if (c->remote->auth_timeout) {
453  g_source_remove(c->remote->auth_timeout);
454  }
455  free(c->remote->buffer);
456  free(c->remote);
457  }
458  free(c);
459 }
460 
469 bool
470 crm_set_client_queue_max(crm_client_t *client, const char *qmax)
471 {
472  if (is_set(client->flags, crm_client_flag_ipc_privileged)) {
473  int qmax_int = crm_int_helper(qmax, NULL);
474 
475  if ((errno == 0) && (qmax_int > 0)) {
476  client->queue_max = qmax_int;
477  return TRUE;
478  }
479  }
480  return FALSE;
481 }
482 
483 int
484 crm_ipcs_client_pid(qb_ipcs_connection_t * c)
485 {
486  struct qb_ipcs_connection_stats stats;
487 
488  stats.client_pid = 0;
489  qb_ipcs_connection_stats_get(c, &stats, 0);
490  return stats.client_pid;
491 }
492 
493 xmlNode *
495 {
496  xmlNode *xml = NULL;
497  char *uncompressed = NULL;
498  char *text = ((char *)data) + sizeof(struct crm_ipc_response_header);
499  struct crm_ipc_response_header *header = data;
500 
501  if (id) {
502  *id = ((struct qb_ipc_response_header *)data)->id;
503  }
504  if (flags) {
505  *flags = header->flags;
506  }
507 
508  if (is_set(header->flags, crm_ipc_proxied)) {
509  /* mark this client as being the endpoint of a proxy connection.
510  * Proxy connections responses are sent on the event channel to avoid
511  * blocking the proxy daemon (crmd) */
513  }
514 
515  if(header->version > PCMK_IPC_VERSION) {
516  crm_err("Filtering incompatible v%d IPC message, we only support versions <= %d",
517  header->version, PCMK_IPC_VERSION);
518  return NULL;
519  }
520 
521  if (header->size_compressed) {
522  int rc = 0;
523  unsigned int size_u = 1 + header->size_uncompressed;
524  uncompressed = calloc(1, size_u);
525 
526  crm_trace("Decompressing message data %u bytes into %u bytes",
527  header->size_compressed, size_u);
528 
529  rc = BZ2_bzBuffToBuffDecompress(uncompressed, &size_u, text, header->size_compressed, 1, 0);
530  text = uncompressed;
531 
532  if (rc != BZ_OK) {
533  crm_err("Decompression failed: %s (%d)", bz2_strerror(rc), rc);
534  free(uncompressed);
535  return NULL;
536  }
537  }
538 
539  CRM_ASSERT(text[header->size_uncompressed - 1] == 0);
540 
541  crm_trace("Received %.200s", text);
542  xml = string2xml(text);
543 
544  free(uncompressed);
545  return xml;
546 }
547 
549 
550 static gboolean
551 crm_ipcs_flush_events_cb(gpointer data)
552 {
553  crm_client_t *c = data;
554 
555  c->event_timer = 0;
557  return FALSE;
558 }
559 
567 static inline void
568 delay_next_flush(crm_client_t *c, unsigned int queue_len)
569 {
570  /* Delay a maximum of 5 seconds */
571  guint delay = (queue_len < 40)? (1000 + 100 * queue_len) : 5000;
572 
573  c->event_timer = g_timeout_add(delay, crm_ipcs_flush_events_cb, c);
574 }
575 
576 ssize_t
578 {
579  ssize_t rc = 0;
580  unsigned int sent = 0;
581  unsigned int queue_len = 0;
582 
583  if (c == NULL) {
584  return pcmk_ok;
585 
586  } else if (c->event_timer) {
587  /* There is already a timer, wait until it goes off */
588  crm_trace("Timer active for %p - %d", c->ipcs, c->event_timer);
589  return pcmk_ok;
590  }
591 
592  queue_len = g_list_length(c->event_queue);
593  while (c->event_queue && sent < 100) {
594  struct crm_ipc_response_header *header = NULL;
595  struct iovec *event = c->event_queue->data;
596 
597  rc = qb_ipcs_event_sendv(c->ipcs, event, 2);
598  if (rc < 0) {
599  break;
600  }
601 
602  sent++;
603  header = event[0].iov_base;
604  if (header->size_compressed) {
605  crm_trace("Event %d to %p[%d] (%lld compressed bytes) sent",
606  header->qb.id, c->ipcs, c->pid, (long long) rc);
607  } else {
608  crm_trace("Event %d to %p[%d] (%lld bytes) sent: %.120s",
609  header->qb.id, c->ipcs, c->pid, (long long) rc,
610  (char *) (event[1].iov_base));
611  }
612 
613  c->event_queue = g_list_remove(c->event_queue, event);
614  free(event[0].iov_base);
615  free(event[1].iov_base);
616  free(event);
617  }
618 
619  queue_len -= sent;
620  if (sent > 0 || queue_len) {
621  crm_trace("Sent %d events (%d remaining) for %p[%d]: %s (%lld)",
622  sent, queue_len, c->ipcs, c->pid,
623  pcmk_strerror(rc < 0 ? rc : 0), (long long) rc);
624  }
625 
626  if (queue_len) {
627 
628  /* Allow clients to briefly fall behind on processing incoming messages,
629  * but drop completely unresponsive clients so the connection doesn't
630  * consume resources indefinitely.
631  */
632  if (queue_len > QB_MAX(c->queue_max, PCMK_IPC_DEFAULT_QUEUE_MAX)) {
633  if ((c->queue_backlog <= 1) || (queue_len < c->queue_backlog)) {
634  /* Don't evict for a new or shrinking backlog */
635  crm_warn("Client with process ID %u has a backlog of %u messages "
636  CRM_XS " %p", c->pid, queue_len, c->ipcs);
637  } else {
638  crm_err("Evicting client with process ID %u due to backlog of %u messages "
639  CRM_XS " %p", c->pid, queue_len, c->ipcs);
640  c->queue_backlog = 0;
641  qb_ipcs_disconnect(c->ipcs);
642  return rc;
643  }
644  }
645 
646  c->queue_backlog = queue_len;
647  delay_next_flush(c, queue_len);
648 
649  } else {
650  /* Event queue is empty, there is no backlog */
651  c->queue_backlog = 0;
652  }
653 
654  return rc;
655 }
656 
657 ssize_t
658 crm_ipc_prepare(uint32_t request, xmlNode * message, struct iovec ** result, uint32_t max_send_size)
659 {
660  static unsigned int biggest = 0;
661  struct iovec *iov;
662  unsigned int total = 0;
663  char *compressed = NULL;
664  char *buffer = dump_xml_unformatted(message);
665  struct crm_ipc_response_header *header = calloc(1, sizeof(struct crm_ipc_response_header));
666 
667  CRM_ASSERT(result != NULL);
668 
669  crm_ipc_init();
670 
671  if (max_send_size == 0) {
672  max_send_size = ipc_buffer_max;
673  }
674 
675  CRM_LOG_ASSERT(max_send_size != 0);
676 
677  *result = NULL;
678  iov = calloc(2, sizeof(struct iovec));
679 
680 
681  iov[0].iov_len = hdr_offset;
682  iov[0].iov_base = header;
683 
684  header->version = PCMK_IPC_VERSION;
685  header->size_uncompressed = 1 + strlen(buffer);
686  total = iov[0].iov_len + header->size_uncompressed;
687 
688  if (total < max_send_size) {
689  iov[1].iov_base = buffer;
690  iov[1].iov_len = header->size_uncompressed;
691 
692  } else {
693  unsigned int new_size = 0;
694 
696  (buffer, header->size_uncompressed, max_send_size, &compressed, &new_size)) {
697 
698  header->flags |= crm_ipc_compressed;
699  header->size_compressed = new_size;
700 
701  iov[1].iov_len = header->size_compressed;
702  iov[1].iov_base = compressed;
703 
704  free(buffer);
705 
706  biggest = QB_MAX(header->size_compressed, biggest);
707 
708  } else {
709  ssize_t rc = -EMSGSIZE;
710 
711  crm_log_xml_trace(message, "EMSGSIZE");
712  biggest = QB_MAX(header->size_uncompressed, biggest);
713 
714  crm_err
715  ("Could not compress the message (%u bytes) into less than the configured ipc limit (%u bytes). "
716  "Set PCMK_ipc_buffer to a higher value (%u bytes suggested)",
717  header->size_uncompressed, max_send_size, 4 * biggest);
718 
719  free(compressed);
720  free(buffer);
721  free(header);
722  free(iov);
723 
724  return rc;
725  }
726  }
727 
728  header->qb.size = iov[0].iov_len + iov[1].iov_len;
729  header->qb.id = (int32_t)request; /* Replying to a specific request */
730 
731  *result = iov;
732  CRM_ASSERT(header->qb.size > 0);
733  return header->qb.size;
734 }
735 
736 ssize_t
737 crm_ipcs_sendv(crm_client_t * c, struct iovec * iov, enum crm_ipc_flags flags)
738 {
739  ssize_t rc;
740  static uint32_t id = 1;
741  struct crm_ipc_response_header *header = iov[0].iov_base;
742 
744  /* _ALL_ replies to proxied connections need to be sent as events */
745  if (is_not_set(flags, crm_ipc_server_event)) {
746  flags |= crm_ipc_server_event;
747  /* this flag lets us know this was originally meant to be a response.
748  * even though we're sending it over the event channel. */
750  }
751  }
752 
753  header->flags |= flags;
754  if (flags & crm_ipc_server_event) {
755  header->qb.id = id++; /* We don't really use it, but doesn't hurt to set one */
756 
757  if (flags & crm_ipc_server_free) {
758  crm_trace("Sending the original to %p[%d]", c->ipcs, c->pid);
759  c->event_queue = g_list_append(c->event_queue, iov);
760 
761  } else {
762  struct iovec *iov_copy = calloc(2, sizeof(struct iovec));
763 
764  crm_trace("Sending a copy to %p[%d]", c->ipcs, c->pid);
765  iov_copy[0].iov_len = iov[0].iov_len;
766  iov_copy[0].iov_base = malloc(iov[0].iov_len);
767  memcpy(iov_copy[0].iov_base, iov[0].iov_base, iov[0].iov_len);
768 
769  iov_copy[1].iov_len = iov[1].iov_len;
770  iov_copy[1].iov_base = malloc(iov[1].iov_len);
771  memcpy(iov_copy[1].iov_base, iov[1].iov_base, iov[1].iov_len);
772 
773  c->event_queue = g_list_append(c->event_queue, iov_copy);
774  }
775 
776  } else {
777  CRM_LOG_ASSERT(header->qb.id != 0); /* Replying to a specific request */
778 
779  rc = qb_ipcs_response_sendv(c->ipcs, iov, 2);
780  if (rc < header->qb.size) {
781  crm_notice("Response %d to %p[%d] (%u bytes) failed: %s (%d)",
782  header->qb.id, c->ipcs, c->pid, header->qb.size, pcmk_strerror(rc), rc);
783 
784  } else {
785  crm_trace("Response %d sent, %lld bytes to %p[%d]",
786  header->qb.id, (long long) rc, c->ipcs, c->pid);
787  }
788 
789  if (flags & crm_ipc_server_free) {
790  free(iov[0].iov_base);
791  free(iov[1].iov_base);
792  free(iov);
793  }
794  }
795 
796  if (flags & crm_ipc_server_event) {
797  rc = crm_ipcs_flush_events(c);
798  } else {
800  }
801 
802  if (rc == -EPIPE || rc == -ENOTCONN) {
803  crm_trace("Client %p disconnected", c->ipcs);
804  }
805 
806  return rc;
807 }
808 
809 ssize_t
810 crm_ipcs_send(crm_client_t * c, uint32_t request, xmlNode * message,
811  enum crm_ipc_flags flags)
812 {
813  struct iovec *iov = NULL;
814  ssize_t rc = 0;
815 
816  if(c == NULL) {
817  return -EDESTADDRREQ;
818  }
819  crm_ipc_init();
820 
821  rc = crm_ipc_prepare(request, message, &iov, ipc_buffer_max);
822  if (rc > 0) {
823  rc = crm_ipcs_sendv(c, iov, flags | crm_ipc_server_free);
824 
825  } else {
826  free(iov);
827  crm_notice("Message to %p[%d] failed: %s (%d)",
828  c->ipcs, c->pid, pcmk_strerror(rc), rc);
829  }
830 
831  return rc;
832 }
833 
834 void
835 crm_ipcs_send_ack(crm_client_t * c, uint32_t request, uint32_t flags, const char *tag, const char *function,
836  int line)
837 {
838  if (flags & crm_ipc_client_response) {
839  xmlNode *ack = create_xml_node(NULL, tag);
840 
841  crm_trace("Ack'ing msg from %s (%p)", crm_client_name(c), c);
842  c->request_id = 0;
843  crm_xml_add(ack, "function", function);
844  crm_xml_add_int(ack, "line", line);
845  crm_ipcs_send(c, request, ack, flags);
846  free_xml(ack);
847  }
848 }
849 
850 /* Client... */
851 
852 #define MIN_MSG_SIZE 12336 /* sizeof(struct qb_ipc_connection_response) */
853 #define MAX_MSG_SIZE 128*1024 /* 128k default */
854 
855 struct crm_ipc_s {
856  struct pollfd pfd;
857 
858  /* the max size we can send/receive over ipc */
859  unsigned int max_buf_size;
860  /* Size of the allocated 'buffer' */
861  unsigned int buf_size;
862  int msg_size;
863  int need_reply;
864  char *buffer;
865  char *name;
866  uint32_t buffer_flags;
867 
868  qb_ipcc_connection_t *ipc;
869 
870 };
871 
872 static unsigned int
873 pick_ipc_buffer(unsigned int max)
874 {
875  static unsigned int global_max = 0;
876 
877  if (global_max == 0) {
878  const char *env = getenv("PCMK_ipc_buffer");
879 
880  if (env) {
881  int env_max = crm_parse_int(env, "0");
882 
883  global_max = (env_max > 0)? QB_MAX(MIN_MSG_SIZE, env_max) : MAX_MSG_SIZE;
884 
885  } else {
886  global_max = MAX_MSG_SIZE;
887  }
888  }
889 
890  return QB_MAX(max, global_max);
891 }
892 
893 crm_ipc_t *
894 crm_ipc_new(const char *name, size_t max_size)
895 {
896  crm_ipc_t *client = NULL;
897 
898  client = calloc(1, sizeof(crm_ipc_t));
899 
900  client->name = strdup(name);
901  client->buf_size = pick_ipc_buffer(max_size);
902  client->buffer = malloc(client->buf_size);
903 
904  /* Clients initiating connection pick the max buf size */
905  client->max_buf_size = client->buf_size;
906 
907  client->pfd.fd = -1;
908  client->pfd.events = POLLIN;
909  client->pfd.revents = 0;
910 
911  return client;
912 }
913 
923 bool
925 {
926  static uid_t cl_uid = 0;
927  static gid_t cl_gid = 0;
928  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
929  int rv;
930 
931  client->need_reply = FALSE;
932  client->ipc = qb_ipcc_connect(client->name, client->buf_size);
933 
934  if (client->ipc == NULL) {
935  crm_debug("Could not establish %s connection: %s (%d)", client->name, pcmk_strerror(errno), errno);
936  return FALSE;
937  }
938 
939  client->pfd.fd = crm_ipc_get_fd(client);
940  if (client->pfd.fd < 0) {
941  rv = errno;
942  /* message already omitted */
943  crm_ipc_close(client);
944  errno = rv;
945  return FALSE;
946  }
947 
948  if (!cl_uid && !cl_gid
949  && (rv = crm_user_lookup(CRM_DAEMON_USER, &cl_uid, &cl_gid)) < 0) {
950  errno = -rv;
951  /* message already omitted */
952  crm_ipc_close(client);
953  errno = -rv;
954  return FALSE;
955  }
956 
957  if (!(rv = crm_ipc_is_authentic_process(client->pfd.fd, cl_uid, cl_gid,
958  &found_pid, &found_uid,
959  &found_gid))) {
960  crm_err("Daemon (IPC %s) is not authentic:"
961  " process %lld (uid: %lld, gid: %lld)",
962  client->name, (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
963  (long long) found_uid, (long long) found_gid);
964  crm_ipc_close(client);
965  errno = ECONNABORTED;
966  return FALSE;
967 
968  } else if (rv < 0) {
969  errno = -rv;
970  crm_perror(LOG_ERR, "Could not verify authenticity of daemon (IPC %s)",
971  client->name);
972  crm_ipc_close(client);
973  errno = -rv;
974  return FALSE;
975  }
976 
977  qb_ipcc_context_set(client->ipc, client);
978 
979 #ifdef HAVE_IPCS_GET_BUFFER_SIZE
980  client->max_buf_size = qb_ipcc_get_buffer_size(client->ipc);
981  if (client->max_buf_size > client->buf_size) {
982  free(client->buffer);
983  client->buffer = calloc(1, client->max_buf_size);
984  client->buf_size = client->max_buf_size;
985  }
986 #endif
987 
988  return TRUE;
989 }
990 
991 void
993 {
994  if (client) {
995  crm_trace("Disconnecting %s IPC connection %p (%p)", client->name, client, client->ipc);
996 
997  if (client->ipc) {
998  qb_ipcc_connection_t *ipc = client->ipc;
999 
1000  client->ipc = NULL;
1001  qb_ipcc_disconnect(ipc);
1002  }
1003  }
1004 }
1005 
1006 void
1008 {
1009  if (client) {
1010  if (client->ipc && qb_ipcc_is_connected(client->ipc)) {
1011  crm_notice("Destroying an active IPC connection to %s", client->name);
1012  /* The next line is basically unsafe
1013  *
1014  * If this connection was attached to mainloop and mainloop is active,
1015  * the 'disconnected' callback will end up back here and we'll end
1016  * up free'ing the memory twice - something that can still happen
1017  * even without this if we destroy a connection and it closes before
1018  * we call exit
1019  */
1020  /* crm_ipc_close(client); */
1021  }
1022  crm_trace("Destroying IPC connection to %s: %p", client->name, client);
1023  free(client->buffer);
1024  free(client->name);
1025  free(client);
1026  }
1027 }
1028 
1029 int
1031 {
1032  int fd = 0;
1033 
1034  if (client && client->ipc && (qb_ipcc_fd_get(client->ipc, &fd) == 0)) {
1035  return fd;
1036  }
1037  errno = EINVAL;
1038  crm_perror(LOG_ERR, "Could not obtain file IPC descriptor for %s",
1039  (client? client->name : "unspecified client"));
1040  return -errno;
1041 }
1042 
1043 bool
1045 {
1046  bool rc = FALSE;
1047 
1048  if (client == NULL) {
1049  crm_trace("No client");
1050  return FALSE;
1051 
1052  } else if (client->ipc == NULL) {
1053  crm_trace("No connection");
1054  return FALSE;
1055 
1056  } else if (client->pfd.fd < 0) {
1057  crm_trace("Bad descriptor");
1058  return FALSE;
1059  }
1060 
1061  rc = qb_ipcc_is_connected(client->ipc);
1062  if (rc == FALSE) {
1063  client->pfd.fd = -EINVAL;
1064  }
1065  return rc;
1066 }
1067 
1075 int
1077 {
1078  int rc;
1079 
1080  CRM_ASSERT(client != NULL);
1081 
1082  if (crm_ipc_connected(client) == FALSE) {
1083  return -ENOTCONN;
1084  }
1085 
1086  client->pfd.revents = 0;
1087  rc = poll(&(client->pfd), 1, 0);
1088  return (rc < 0)? -errno : rc;
1089 }
1090 
1091 static int
1092 crm_ipc_decompress(crm_ipc_t * client)
1093 {
1094  struct crm_ipc_response_header *header = (struct crm_ipc_response_header *)(void*)client->buffer;
1095 
1096  if (header->size_compressed) {
1097  int rc = 0;
1098  unsigned int size_u = 1 + header->size_uncompressed;
1099  /* never let buf size fall below our max size required for ipc reads. */
1100  unsigned int new_buf_size = QB_MAX((hdr_offset + size_u), client->max_buf_size);
1101  char *uncompressed = calloc(1, new_buf_size);
1102 
1103  crm_trace("Decompressing message data %u bytes into %u bytes",
1104  header->size_compressed, size_u);
1105 
1106  rc = BZ2_bzBuffToBuffDecompress(uncompressed + hdr_offset, &size_u,
1107  client->buffer + hdr_offset, header->size_compressed, 1, 0);
1108 
1109  if (rc != BZ_OK) {
1110  crm_err("Decompression failed: %s (%d)", bz2_strerror(rc), rc);
1111  free(uncompressed);
1112  return -EILSEQ;
1113  }
1114 
1115  /*
1116  * This assert no longer holds true. For an identical msg, some clients may
1117  * require compression, and others may not. If that same msg (event) is sent
1118  * to multiple clients, it could result in some clients receiving a compressed
1119  * msg even though compression was not explicitly required for them.
1120  *
1121  * CRM_ASSERT((header->size_uncompressed + hdr_offset) >= ipc_buffer_max);
1122  */
1123  CRM_ASSERT(size_u == header->size_uncompressed);
1124 
1125  memcpy(uncompressed, client->buffer, hdr_offset); /* Preserve the header */
1126  header = (struct crm_ipc_response_header *)(void*)uncompressed;
1127 
1128  free(client->buffer);
1129  client->buf_size = new_buf_size;
1130  client->buffer = uncompressed;
1131  }
1132 
1133  CRM_ASSERT(client->buffer[hdr_offset + header->size_uncompressed - 1] == 0);
1134  return pcmk_ok;
1135 }
1136 
1137 long
1139 {
1140  struct crm_ipc_response_header *header = NULL;
1141 
1142  CRM_ASSERT(client != NULL);
1143  CRM_ASSERT(client->ipc != NULL);
1144  CRM_ASSERT(client->buffer != NULL);
1145 
1146  crm_ipc_init();
1147 
1148  client->buffer[0] = 0;
1149  client->msg_size = qb_ipcc_event_recv(client->ipc, client->buffer,
1150  client->buf_size, 0);
1151  if (client->msg_size >= 0) {
1152  int rc = crm_ipc_decompress(client);
1153 
1154  if (rc != pcmk_ok) {
1155  return rc;
1156  }
1157 
1158  header = (struct crm_ipc_response_header *)(void*)client->buffer;
1159  if(header->version > PCMK_IPC_VERSION) {
1160  crm_err("Filtering incompatible v%d IPC message, we only support versions <= %d",
1161  header->version, PCMK_IPC_VERSION);
1162  return -EBADMSG;
1163  }
1164 
1165  crm_trace("Received %s event %d, size=%u, rc=%d, text: %.100s",
1166  client->name, header->qb.id, header->qb.size, client->msg_size,
1167  client->buffer + hdr_offset);
1168 
1169  } else {
1170  crm_trace("No message from %s received: %s", client->name, pcmk_strerror(client->msg_size));
1171  }
1172 
1173  if (crm_ipc_connected(client) == FALSE || client->msg_size == -ENOTCONN) {
1174  crm_err("Connection to %s failed", client->name);
1175  }
1176 
1177  if (header) {
1178  /* Data excluding the header */
1179  return header->size_uncompressed;
1180  }
1181  return -ENOMSG;
1182 }
1183 
1184 const char *
1186 {
1187  CRM_ASSERT(client != NULL);
1188  return client->buffer + sizeof(struct crm_ipc_response_header);
1189 }
1190 
1191 uint32_t
1193 {
1194  struct crm_ipc_response_header *header = NULL;
1195 
1196  CRM_ASSERT(client != NULL);
1197  if (client->buffer == NULL) {
1198  return 0;
1199  }
1200 
1201  header = (struct crm_ipc_response_header *)(void*)client->buffer;
1202  return header->flags;
1203 }
1204 
1205 const char *
1207 {
1208  CRM_ASSERT(client != NULL);
1209  return client->name;
1210 }
1211 
1212 static int
1213 internal_ipc_send_recv(crm_ipc_t * client, const void *iov)
1214 {
1215  int rc = 0;
1216 
1217  do {
1218  rc = qb_ipcc_sendv_recv(client->ipc, iov, 2, client->buffer, client->buf_size, -1);
1219  } while (rc == -EAGAIN && crm_ipc_connected(client));
1220 
1221  return rc;
1222 }
1223 
1224 static int
1225 internal_ipc_send_request(crm_ipc_t * client, const void *iov, int ms_timeout)
1226 {
1227  int rc = 0;
1228  time_t timeout = time(NULL) + 1 + (ms_timeout / 1000);
1229 
1230  do {
1231  rc = qb_ipcc_sendv(client->ipc, iov, 2);
1232  } while (rc == -EAGAIN && time(NULL) < timeout && crm_ipc_connected(client));
1233 
1234  return rc;
1235 }
1236 
1237 static int
1238 internal_ipc_get_reply(crm_ipc_t * client, int request_id, int ms_timeout)
1239 {
1240  time_t timeout = time(NULL) + 1 + (ms_timeout / 1000);
1241  int rc = 0;
1242 
1243  crm_ipc_init();
1244 
1245  /* get the reply */
1246  crm_trace("client %s waiting on reply to msg id %d", client->name, request_id);
1247  do {
1248 
1249  rc = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, 1000);
1250  if (rc > 0) {
1251  struct crm_ipc_response_header *hdr = NULL;
1252 
1253  int rc = crm_ipc_decompress(client);
1254 
1255  if (rc != pcmk_ok) {
1256  return rc;
1257  }
1258 
1259  hdr = (struct crm_ipc_response_header *)(void*)client->buffer;
1260  if (hdr->qb.id == request_id) {
1261  /* Got it */
1262  break;
1263  } else if (hdr->qb.id < request_id) {
1264  xmlNode *bad = string2xml(crm_ipc_buffer(client));
1265 
1266  crm_err("Discarding old reply %d (need %d)", hdr->qb.id, request_id);
1267  crm_log_xml_notice(bad, "OldIpcReply");
1268 
1269  } else {
1270  xmlNode *bad = string2xml(crm_ipc_buffer(client));
1271 
1272  crm_err("Discarding newer reply %d (need %d)", hdr->qb.id, request_id);
1273  crm_log_xml_notice(bad, "ImpossibleReply");
1274  CRM_ASSERT(hdr->qb.id <= request_id);
1275  }
1276  } else if (crm_ipc_connected(client) == FALSE) {
1277  crm_err("Server disconnected client %s while waiting for msg id %d", client->name,
1278  request_id);
1279  break;
1280  }
1281 
1282  } while (time(NULL) < timeout);
1283 
1284  return rc;
1285 }
1286 
1287 int
1288 crm_ipc_send(crm_ipc_t * client, xmlNode * message, enum crm_ipc_flags flags, int32_t ms_timeout,
1289  xmlNode ** reply)
1290 {
1291  long rc = 0;
1292  struct iovec *iov;
1293  static uint32_t id = 0;
1294  static int factor = 8;
1295  struct crm_ipc_response_header *header;
1296 
1297  crm_ipc_init();
1298 
1299  if (client == NULL) {
1300  crm_notice("Invalid connection");
1301  return -ENOTCONN;
1302 
1303  } else if (crm_ipc_connected(client) == FALSE) {
1304  /* Don't even bother */
1305  crm_notice("Connection to %s closed", client->name);
1306  return -ENOTCONN;
1307  }
1308 
1309  if (ms_timeout == 0) {
1310  ms_timeout = 5000;
1311  }
1312 
1313  if (client->need_reply) {
1314  crm_trace("Trying again to obtain pending reply from %s", client->name);
1315  rc = qb_ipcc_recv(client->ipc, client->buffer, client->buf_size, ms_timeout);
1316  if (rc < 0) {
1317  crm_warn("Sending to %s (%p) is disabled until pending reply is received", client->name,
1318  client->ipc);
1319  return -EALREADY;
1320 
1321  } else {
1322  crm_notice("Lost reply from %s (%p) finally arrived, sending re-enabled", client->name,
1323  client->ipc);
1324  client->need_reply = FALSE;
1325  }
1326  }
1327 
1328  id++;
1329  CRM_LOG_ASSERT(id != 0); /* Crude wrap-around detection */
1330  rc = crm_ipc_prepare(id, message, &iov, client->max_buf_size);
1331  if(rc < 0) {
1332  return rc;
1333  }
1334 
1335  header = iov[0].iov_base;
1336  header->flags |= flags;
1337 
1338  if(is_set(flags, crm_ipc_proxied)) {
1339  /* Don't look for a synchronous response */
1341  }
1342 
1343  if(header->size_compressed) {
1344  if(factor < 10 && (client->max_buf_size / 10) < (rc / factor)) {
1345  crm_notice("Compressed message exceeds %d0%% of the configured ipc limit (%u bytes), "
1346  "consider setting PCMK_ipc_buffer to %u or higher",
1347  factor, client->max_buf_size, 2 * client->max_buf_size);
1348  factor++;
1349  }
1350  }
1351 
1352  crm_trace("Sending from client: %s request id: %d bytes: %u timeout:%d msg...",
1353  client->name, header->qb.id, header->qb.size, ms_timeout);
1354 
1355  if (ms_timeout > 0 || is_not_set(flags, crm_ipc_client_response)) {
1356 
1357  rc = internal_ipc_send_request(client, iov, ms_timeout);
1358 
1359  if (rc <= 0) {
1360  crm_trace("Failed to send from client %s request %d with %u bytes...",
1361  client->name, header->qb.id, header->qb.size);
1362  goto send_cleanup;
1363 
1364  } else if (is_not_set(flags, crm_ipc_client_response)) {
1365  crm_trace("Message sent, not waiting for reply to %d from %s to %u bytes...",
1366  header->qb.id, client->name, header->qb.size);
1367 
1368  goto send_cleanup;
1369  }
1370 
1371  rc = internal_ipc_get_reply(client, header->qb.id, ms_timeout);
1372  if (rc < 0) {
1373  /* No reply, for now, disable sending
1374  *
1375  * The alternative is to close the connection since we don't know
1376  * how to detect and discard out-of-sequence replies
1377  *
1378  * TODO - implement the above
1379  */
1380  client->need_reply = TRUE;
1381  }
1382 
1383  } else {
1384  rc = internal_ipc_send_recv(client, iov);
1385  }
1386 
1387  if (rc > 0) {
1388  struct crm_ipc_response_header *hdr = (struct crm_ipc_response_header *)(void*)client->buffer;
1389 
1390  crm_trace("Received response %d, size=%u, rc=%ld, text: %.200s", hdr->qb.id, hdr->qb.size,
1391  rc, crm_ipc_buffer(client));
1392 
1393  if (reply) {
1394  *reply = string2xml(crm_ipc_buffer(client));
1395  }
1396 
1397  } else {
1398  crm_trace("Response not received: rc=%ld, errno=%d", rc, errno);
1399  }
1400 
1401  send_cleanup:
1402  if (crm_ipc_connected(client) == FALSE) {
1403  crm_notice("Connection to %s closed: %s (%ld)", client->name, pcmk_strerror(rc), rc);
1404 
1405  } else if (rc == -ETIMEDOUT) {
1406  crm_warn("Request %d to %s (%p) failed: %s (%ld) after %dms",
1407  header->qb.id, client->name, client->ipc, pcmk_strerror(rc), rc, ms_timeout);
1408  crm_write_blackbox(0, NULL);
1409 
1410  } else if (rc <= 0) {
1411  crm_warn("Request %d to %s (%p) failed: %s (%ld)",
1412  header->qb.id, client->name, client->ipc, pcmk_strerror(rc), rc);
1413  }
1414 
1415  free(header);
1416  free(iov[1].iov_base);
1417  free(iov);
1418  return rc;
1419 }
1420 
1421 int
1422 crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid,
1423  pid_t *gotpid, uid_t *gotuid, gid_t *gotgid) {
1424  int ret = 0;
1425  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1426 #if defined(US_AUTH_PEERCRED_UCRED)
1427  struct ucred ucred;
1428  socklen_t ucred_len = sizeof(ucred);
1429 
1430  if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1431  &ucred, &ucred_len)
1432  && ucred_len == sizeof(ucred)) {
1433  found_pid = ucred.pid; found_uid = ucred.uid; found_gid = ucred.gid;
1434 
1435 #elif defined(US_AUTH_PEERCRED_SOCKPEERCRED)
1436  struct sockpeercred sockpeercred;
1437  socklen_t sockpeercred_len = sizeof(sockpeercred);
1438 
1439  if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED,
1440  &sockpeercred, &sockpeercred_len)
1441  && sockpeercred_len == sizeof(sockpeercred_len)) {
1442  found_pid = sockpeercred.pid;
1443  found_uid = sockpeercred.uid; found_gid = sockpeercred.gid;
1444 
1445 #elif defined(US_AUTH_GETPEEREID)
1446  if (!getpeereid(sock, &found_uid, &found_gid)) {
1447  found_pid = PCMK__SPECIAL_PID; /* cannot obtain PID (FreeBSD) */
1448 
1449 #elif defined(US_AUTH_GETPEERUCRED)
1450  ucred_t *ucred;
1451  if (!getpeerucred(sock, &ucred)) {
1452  errno = 0;
1453  found_pid = ucred_getpid(ucred);
1454  found_uid = ucred_geteuid(ucred); found_gid = ucred_getegid(ucred);
1455  ret = -errno;
1456  ucred_free(ucred);
1457  if (ret) {
1458  return (ret < 0) ? ret : -pcmk_err_generic;
1459  }
1460 
1461 #else
1462 # error "No way to authenticate a Unix socket peer"
1463  errno = 0;
1464  if (0) {
1465 #endif
1466  if (gotpid != NULL) {
1467  *gotpid = found_pid;
1468  }
1469  if (gotuid != NULL) {
1470  *gotuid = found_uid;
1471  }
1472  if (gotgid != NULL) {
1473  *gotgid = found_gid;
1474  }
1475  ret = (found_uid == 0 || found_uid == refuid || found_gid == refgid);
1476  } else {
1477  ret = (errno > 0) ? -errno : -pcmk_err_generic;
1478  }
1479 
1480  return ret;
1481 }
1482 
1483 int
1484 pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid,
1485  gid_t refgid, pid_t *gotpid) {
1486  static char last_asked_name[PATH_MAX / 2] = ""; /* log spam prevention */
1487  int fd, ret = 0;
1488  pid_t found_pid = 0; uid_t found_uid = 0; gid_t found_gid = 0;
1489  qb_ipcc_connection_t *c;
1490 
1491  if ((c = qb_ipcc_connect(name, 0)) == NULL) {
1492  crm_info("Could not connect to %s IPC: %s", name, strerror(errno));
1493 
1494  } else if ((ret = qb_ipcc_fd_get(c, &fd))) {
1495  crm_err("Could not get fd from %s IPC: %s (%d)", name,
1496  strerror(-ret), -ret);
1497  ret = -1;
1498 
1499  } else if ((ret = crm_ipc_is_authentic_process(fd, refuid, refgid,
1500  &found_pid, &found_uid,
1501  &found_gid)) < 0) {
1502  if (ret == -pcmk_err_generic) {
1503  crm_err("Could not get peer credentials from %s IPC", name);
1504  } else {
1505  crm_err("Could not get peer credentials from %s IPC: %s (%d)",
1506  name, strerror(-ret), -ret);
1507  }
1508  ret = -1;
1509 
1510  } else {
1511  if (gotpid != NULL) {
1512  *gotpid = found_pid;
1513  }
1514 
1515  if (!ret) {
1516  crm_err("Daemon (IPC %s) effectively blocked with unauthorized"
1517  " process %lld (uid: %lld, gid: %lld)",
1518  name, (long long) PCMK__SPECIAL_PID_AS_0(found_pid),
1519  (long long) found_uid, (long long) found_gid);
1520  ret = -2;
1521  } else if ((found_uid != refuid || found_gid != refgid)
1522  && strncmp(last_asked_name, name, sizeof(last_asked_name))) {
1523  if (!found_uid && refuid) {
1524  crm_warn("Daemon (IPC %s) runs as root, whereas the expected"
1525  " credentials are %lld:%lld, hazard of violating"
1526  " the least privilege principle",
1527  name, (long long) refuid, (long long) refgid);
1528  } else {
1529  crm_notice("Daemon (IPC %s) runs as %lld:%lld, whereas the"
1530  " expected credentials are %lld:%lld, which may"
1531  " mean a different set of privileges than expected",
1532  name, (long long) found_uid, (long long) found_gid,
1533  (long long) refuid, (long long) refgid);
1534  }
1535  memccpy(last_asked_name, name, '\0', sizeof(last_asked_name));
1536  }
1537  }
1538 
1539  if (ret) { /* here, !ret only when we could not initially connect */
1540  qb_ipcc_disconnect(c);
1541  }
1542 
1543  return ret;
1544 }
1545 
1546 
1547 /* Utils */
1548 
1549 xmlNode *
1550 create_hello_message(const char *uuid,
1551  const char *client_name, const char *major_version, const char *minor_version)
1552 {
1553  xmlNode *hello_node = NULL;
1554  xmlNode *hello = NULL;
1555 
1556  if (uuid == NULL || strlen(uuid) == 0
1557  || client_name == NULL || strlen(client_name) == 0
1558  || major_version == NULL || strlen(major_version) == 0
1559  || minor_version == NULL || strlen(minor_version) == 0) {
1560  crm_err("Missing fields, Hello message will not be valid.");
1561  return NULL;
1562  }
1563 
1564  hello_node = create_xml_node(NULL, XML_TAG_OPTIONS);
1565  crm_xml_add(hello_node, "major_version", major_version);
1566  crm_xml_add(hello_node, "minor_version", minor_version);
1567  crm_xml_add(hello_node, "client_name", client_name);
1568  crm_xml_add(hello_node, "client_uuid", uuid);
1569 
1570  crm_trace("creating hello message");
1571  hello = create_request(CRM_OP_HELLO, hello_node, NULL, NULL, client_name, uuid);
1572  free_xml(hello_node);
1573 
1574  return hello;
1575 }
#define F_CRM_TASK
Definition: msg_xml.h:56
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
const char * crm_ipc_buffer(crm_ipc_t *client)
Definition: ipc.c:1185
#define F_CRM_REFERENCE
Definition: msg_xml.h:62
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
Definition: logging.c:435
A dumping ground.
#define F_TYPE
Definition: msg_xml.h:34
void crm_ipc_close(crm_ipc_t *client)
Definition: ipc.c:992
#define crm_notice(fmt, args...)
Definition: logging.h:276
char * crm_generate_uuid(void)
Definition: utils.c:1279
uint32_t crm_ipc_buffer_flags(crm_ipc_t *client)
Definition: ipc.c:1192
int crm_ipc_send(crm_ipc_t *client, xmlNode *message, enum crm_ipc_flags flags, int32_t ms_timeout, xmlNode **reply)
Definition: ipc.c:1288
#define F_CRM_HOST_TO
Definition: msg_xml.h:57
#define XML_TAG_OPTIONS
Definition: msg_xml.h:122
const char * pcmk_strerror(int rc)
Definition: logging.c:1017
crm_client_t * crm_client_get(qb_ipcs_connection_t *c)
Definition: ipc.c:211
uint32_t flags
Definition: ipcs.h:83
qb_ipcs_connection_t * ipcs
Definition: ipcs.h:94
#define F_CRM_MSG_TYPE
Definition: msg_xml.h:58
uint32_t size
Definition: internal.h:80
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
Definition: nvpair.c:324
int request_id
Definition: ipcs.h:82
#define CRM_FEATURE_SET
Definition: crm.h:26
#define F_CRM_HOST_FROM
Definition: msg_xml.h:61
#define pcmk_ok
Definition: error.h:45
#define T_CRM
Definition: msg_xml.h:46
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:81
bool crm_set_client_queue_max(crm_client_t *client, const char *qmax)
Raise IPC eviction threshold for a client, if allowed.
Definition: ipc.c:470
crm_client_t * crm_client_get_by_id(const char *id)
Definition: ipc.c:222
xmlNode * create_reply_adv(xmlNode *original_request, xmlNode *xml_response_data, const char *origin)
Definition: ipc.c:154
char * buffer
Definition: ipcs.h:44
unsigned int queue_max
Definition: ipcs.h:99
#define PCMK__SPECIAL_PID_AS_0(p)
Definition: ipc_internal.h:34
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
Definition: nvpair.c:216
bool crm_ipc_connect(crm_ipc_t *client)
Establish an IPC connection to a Pacemaker component.
Definition: ipc.c:924
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:157
#define PCMK_IPC_VERSION
Definition: ipc.c:42
#define PCMK__SPECIAL_PID
Definition: ipc_internal.h:25
struct crm_remote_s * remote
Definition: ipcs.h:96
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
Definition: utils.c:424
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:176
void crm_client_destroy(crm_client_t *c)
Definition: ipc.c:415
int crm_ipc_get_fd(crm_ipc_t *client)
Definition: ipc.c:1030
void crm_client_init(void)
Definition: ipc.c:256
int crm_ipc_is_authentic_process(int sock, uid_t refuid, gid_t refgid, pid_t *gotpid, uid_t *gotuid, gid_t *gotgid)
Check the authenticity of the IPC socket peer process.
Definition: ipc.c:1422
#define clear_bit(word, bit)
Definition: crm_internal.h:211
void crm_client_disconnect_all(qb_ipcs_service_t *service)
Definition: ipc.c:278
char * strerror(int errnum)
ssize_t crm_ipc_prepare(uint32_t request, xmlNode *message, struct iovec **result, uint32_t max_send_size)
Definition: ipc.c:658
char * user
Definition: ipcs.h:76
ssize_t crm_ipcs_flush_events(crm_client_t *c)
Definition: ipc.c:577
xmlNode * string2xml(const char *input)
Definition: xml.c:2152
char version[256]
Definition: plugin.c:84
#define MAX_MSG_SIZE
Definition: ipc.c:853
#define XML_ATTR_REQUEST
Definition: msg_xml.h:127
ssize_t crm_ipcs_sendv(crm_client_t *c, struct iovec *iov, enum crm_ipc_flags flags)
Definition: ipc.c:737
#define crm_warn(fmt, args...)
Definition: logging.h:275
crm_client_t * crm_client_new(qb_ipcs_connection_t *c, uid_t uid_client, gid_t gid_client)
Definition: ipc.c:369
#define set_bit(word, bit)
Definition: crm_internal.h:210
#define crm_debug(fmt, args...)
Definition: logging.h:279
#define F_CRM_SYS_TO
Definition: msg_xml.h:59
struct crm_ipc_s crm_ipc_t
Definition: ipc.h:52
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
Definition: nvpair.c:393
const char * crm_ipc_name(crm_ipc_t *client)
Definition: ipc.c:1206
GList * event_queue
Definition: ipcs.h:87
GHashTable * client_connections
Definition: ipc.c:208
unsigned int crm_ipc_default_buffer_size(void)
Definition: ipc.c:71
#define crm_trace(fmt, args...)
Definition: logging.h:280
void crm_ipc_destroy(crm_ipc_t *client)
Definition: ipc.c:1007
xmlNode * create_xml_node(xmlNode *parent, const char *name)
Definition: xml.c:1977
#define pcmk_err_generic
Definition: error.h:48
#define CRM_DAEMON_USER
Definition: config.h:47
gboolean add_message_xml(xmlNode *msg, const char *field, xmlNode *xml)
Definition: xml.c:2566
void free_xml(xmlNode *child)
Definition: xml.c:2108
void crm_ipcs_send_ack(crm_client_t *c, uint32_t request, uint32_t flags, const char *tag, const char *function, int line)
Definition: ipc.c:835
unsigned int queue_backlog
Definition: ipcs.h:98
xmlNode * crm_ipcs_recv(crm_client_t *c, void *data, size_t size, uint32_t *id, uint32_t *flags)
Definition: ipc.c:494
int auth_timeout
Definition: ipcs.h:47
#define F_CRM_DATA
Definition: msg_xml.h:55
#define CRM_XS
Definition: logging.h:42
crm_client_t * crm_client_alloc(void *key)
Allocate a new crm_client_t object and generate its ID.
Definition: ipc.c:360
bool crm_compress_string(const char *data, int length, int max, char **result, unsigned int *result_len)
Definition: strings.c:445
ssize_t crm_ipcs_send(crm_client_t *c, uint32_t request, xmlNode *message, enum crm_ipc_flags flags)
Definition: ipc.c:810
#define PCMK_IPC_DEFAULT_QUEUE_MAX
Definition: ipc.c:45
int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid, gid_t refgid, pid_t *gotpid)
Definition: ipc.c:1484
uint pid
Definition: ipcs.h:69
int event_timer
Definition: ipcs.h:86
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:252
xmlNode * create_hello_message(const char *uuid, const char *client_name, const char *major_version, const char *minor_version)
Definition: ipc.c:1550
#define CRM_OP_HELLO
Definition: crm.h:113
#define crm_err(fmt, args...)
Definition: logging.h:274
const char * bz2_strerror(int rc)
Definition: logging.c:1390
#define F_CRM_SYS_FROM
Definition: msg_xml.h:60
#define crm_log_xml_notice(xml, text)
Definition: logging.h:285
char * dump_xml_unformatted(xmlNode *msg)
Definition: xml.c:3220
int crm_ipc_ready(crm_ipc_t *client)
Check whether an IPC connection is ready to be read.
Definition: ipc.c:1076
#define uint32_t
Definition: stdint.in.h:158
#define XML_ATTR_RESPONSE
Definition: msg_xml.h:128
#define CRM_ASSERT(expr)
Definition: error.h:20
char data[0]
Definition: internal.h:86
long crm_ipc_read(crm_ipc_t *client)
Definition: ipc.c:1138
char * id
Definition: ipcs.h:74
#define uint8_t
Definition: stdint.in.h:144
Wrappers for and extensions to libqb IPC.
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
Definition: utils.c:414
#define F_CRM_ORIGIN
Definition: msg_xml.h:64
int crm_ipcs_client_pid(qb_ipcs_connection_t *c)
Definition: ipc.c:484
#define crm_log_xml_trace(xml, text)
Definition: logging.h:288
void crm_client_cleanup(void)
Definition: ipc.c:265
enum client_type kind
Definition: ipcs.h:92
const char * crm_client_name(crm_client_t *c)
Definition: ipc.c:242
bool crm_ipc_connected(crm_ipc_t *client)
Definition: ipc.c:1044
crm_ipc_t * crm_ipc_new(const char *name, size_t max_size)
Definition: ipc.c:894
char * name
Definition: ipcs.h:75
crm_ipc_flags
Definition: ipc.h:32
xmlNode * create_request_adv(const char *task, xmlNode *msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *origin)
Definition: ipc.c:109
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
Definition: ipc.h:25
#define crm_info(fmt, args...)
Definition: logging.h:277
char * uid2username(uid_t uid)
#define F_CRM_VERSION
Definition: msg_xml.h:63
uint64_t flags
Definition: remote.c:156
#define MIN_MSG_SIZE
Definition: ipc.c:852
enum crm_ais_msg_types type
Definition: internal.h:79
#define int32_t
Definition: stdint.in.h:157