root/include/crm/common/ipc_internal.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 /*
   2  * Copyright 2013-2021 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 #ifndef PCMK__IPC_INTERNAL_H
  11 #define PCMK__IPC_INTERNAL_H
  12 
  13 #ifdef __cplusplus
  14 extern "C" {
  15 #endif
  16 
  17 #include <stdbool.h>                // bool
  18 #include <stdint.h>                 // uint32_t, uint64_t, UINT64_C()
  19 #include <sys/uio.h>                // struct iovec
  20 #include <sys/types.h>              // uid_t, gid_t, pid_t, size_t
  21 
  22 #ifdef HAVE_GNUTLS_GNUTLS_H
  23 #  include <gnutls/gnutls.h>        // gnutls_session_t
  24 #endif
  25 
  26 #include <glib.h>                   // guint, gpointer, GQueue, ...
  27 #include <libxml/tree.h>            // xmlNode
  28 #include <qb/qbipcs.h>              // qb_ipcs_connection_t, ...
  29 
  30 #include <crm_config.h>             // US_AUTH_GETPEEREID
  31 #include <crm/common/ipc.h>
  32 #include <crm/common/mainloop.h>    // mainloop_io_t
  33 
  34 /* denotes "non yieldable PID" on FreeBSD, or actual PID1 in scenarios that
  35    require a delicate handling anyway (socket-based activation with systemd);
  36    we can be reasonably sure that this PID is never possessed by the actual
  37    child daemon, as it gets taken either by the proper init, or by pacemakerd
  38    itself (i.e. this precludes anything else); note that value of zero
  39    is meant to carry "unset" meaning, and better not to bet on/conditionalize
  40    over signedness of pid_t */
  41 #define PCMK__SPECIAL_PID  1
  42 
  43 // Timeout (in seconds) to use for IPC client sends, reply waits, etc.
  44 #define PCMK__IPC_TIMEOUT 120
  45 
  46 #if defined(US_AUTH_GETPEEREID)
  47 /* on FreeBSD, we don't want to expose "non-yieldable PID" (leading to
  48    "IPC liveness check only") as its nominal representation, which could
  49    cause confusion -- this is unambiguous as long as there's no
  50    socket-based activation like with systemd (very improbable) */
  51 #define PCMK__SPECIAL_PID_AS_0(p)  (((p) == PCMK__SPECIAL_PID) ? 0 : (p))
  52 #else
  53 #define PCMK__SPECIAL_PID_AS_0(p)  (p)
  54 #endif
  55 
  56 /*!
  57  * \internal
  58  * \brief Check the authenticity and liveness of the process via IPC end-point
  59  *
  60  * When IPC daemon under given IPC end-point (name) detected, its authenticity
  61  * is verified by the means of comparing against provided referential UID and
  62  * GID, and the result of this check can be deduced from the return value.
  63  * As an exception, referential UID of 0 (~ root) satisfies arbitrary
  64  * detected daemon's credentials.
  65  *
  66  * \param[in]  name    IPC name to base the search on
  67  * \param[in]  refuid  referential UID to check against
  68  * \param[in]  refgid  referential GID to check against
  69  * \param[out] gotpid  to optionally store obtained PID of the found process
  70  *                     upon returning 1 or -2
  71  *                     (not available on FreeBSD, special value of 1,
  72  *                     see PCMK__SPECIAL_PID, used instead, and the caller
  73  *                     is required to special case this value respectively)
  74  *
  75  * \return Standard Pacemaker return code
  76  *
  77  * \note Return codes of particular interest include pcmk_rc_ipc_unresponsive
  78  *       indicating that no trace of IPC liveness was detected, and
  79  *       pcmk_rc_ipc_unauthorized indicating that the IPC endpoint is blocked by
  80  *       an unauthorized process.
  81  * \note This function emits a log message for return codes other than
  82  *       pcmk_rc_ok and pcmk_rc_ipc_unresponsive, and when there isn't a perfect
  83  *       match in respect to \p reguid and/or \p refgid, for a possible
  84  *       least privilege principle violation.
  85  *
  86  * \see crm_ipc_is_authentic_process
  87  */
  88 int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid,
  89                                           gid_t refgid, pid_t *gotpid);
  90 
  91 
  92 /*
  93  * Server-related
  94  */
  95 
  96 typedef struct pcmk__client_s pcmk__client_t;
  97 
  98 struct pcmk__remote_s {
  99     /* Shared */
 100     char *buffer;
 101     size_t buffer_size;
 102     size_t buffer_offset;
 103     int auth_timeout;
 104     int tcp_socket;
 105     mainloop_io_t *source;
 106 
 107     /* CIB-only */
 108     bool authenticated;
 109     char *token;
 110 
 111     /* TLS only */
 112 #  ifdef HAVE_GNUTLS_GNUTLS_H
 113     gnutls_session_t *tls_session;
 114     bool tls_handshake_complete;
 115 #  endif
 116 };
 117 
 118 enum pcmk__client_flags {
 119     // Lower 32 bits are reserved for server (not library) use
 120 
 121     // Next 8 bits are reserved for client type (sort of a cheap enum)
 122     pcmk__client_ipc        = (UINT64_C(1) << 32), // Client uses plain IPC
 123     pcmk__client_tcp        = (UINT64_C(1) << 33), // Client uses TCP connection
 124 #  ifdef HAVE_GNUTLS_GNUTLS_H
 125     pcmk__client_tls        = (UINT64_C(1) << 34), // Client uses TCP with TLS
 126 #  endif
 127 
 128     // The rest are client attributes
 129     pcmk__client_proxied    = (UINT64_C(1) << 40), // Client IPC is proxied
 130     pcmk__client_privileged = (UINT64_C(1) << 41), // root or cluster user
 131     pcmk__client_to_proxy   = (UINT64_C(1) << 42), // Local client to be proxied
 132 };
 133 
 134 #define PCMK__CLIENT_TYPE(client) ((client)->flags & UINT64_C(0xff00000000))
 135 
 136 struct pcmk__client_s {
 137     unsigned int pid;
 138 
 139     char *id;
 140     char *name;
 141     char *user;
 142     uint64_t flags; // Group of pcmk__client_flags
 143 
 144     int request_id;
 145     void *userdata;
 146 
 147     int event_timer;
 148     GQueue *event_queue;
 149 
 150     /* Depending on the client type, only some of the following will be
 151      * populated/valid. @TODO Maybe convert to a union.
 152      */
 153 
 154     qb_ipcs_connection_t *ipcs; /* IPC */
 155 
 156     struct pcmk__remote_s *remote;        /* TCP/TLS */
 157 
 158     unsigned int queue_backlog; /* IPC queue length after last flush */
 159     unsigned int queue_max;     /* Evict client whose queue grows this big */
 160 };
 161 
 162 #define pcmk__set_client_flags(client, flags_to_set) do {               \
 163         (client)->flags = pcmk__set_flags_as(__func__, __LINE__,        \
 164             LOG_TRACE,                                                  \
 165             "Client", pcmk__client_name(client),                        \
 166             (client)->flags, (flags_to_set), #flags_to_set);            \
 167     } while (0)
 168 
 169 #define pcmk__clear_client_flags(client, flags_to_clear) do {           \
 170         (client)->flags = pcmk__clear_flags_as(__func__, __LINE__,      \
 171             LOG_TRACE,                                                  \
 172             "Client", pcmk__client_name(client),                        \
 173             (client)->flags, (flags_to_clear), #flags_to_clear);        \
 174     } while (0)
 175 
 176 #define pcmk__set_ipc_flags(ipc_flags, ipc_name, flags_to_set) do {         \
 177         ipc_flags = pcmk__set_flags_as(__func__, __LINE__, LOG_TRACE,       \
 178                                        "IPC", (ipc_name),                   \
 179                                        (ipc_flags), (flags_to_set),         \
 180                                        #flags_to_set);                      \
 181     } while (0)
 182 
 183 #define pcmk__clear_ipc_flags(ipc_flags, ipc_name, flags_to_clear) do {     \
 184         ipc_flags = pcmk__clear_flags_as(__func__, __LINE__, LOG_TRACE,     \
 185                                          "IPC", (ipc_name),                 \
 186                                          (ipc_flags), (flags_to_clear),     \
 187                                          #flags_to_clear);                  \
 188     } while (0)
 189 
 190 guint pcmk__ipc_client_count(void);
 191 void pcmk__foreach_ipc_client(GHFunc func, gpointer user_data);
 192 
 193 void pcmk__client_cleanup(void);
 194 
 195 pcmk__client_t *pcmk__find_client(qb_ipcs_connection_t *c);
 196 pcmk__client_t *pcmk__find_client_by_id(const char *id);
 197 const char *pcmk__client_name(pcmk__client_t *c);
 198 const char *pcmk__client_type_str(uint64_t client_type);
 199 
 200 pcmk__client_t *pcmk__new_unauth_client(void *key);
 201 pcmk__client_t *pcmk__new_client(qb_ipcs_connection_t *c, uid_t uid, gid_t gid);
 202 void pcmk__free_client(pcmk__client_t *c);
 203 void pcmk__drop_all_clients(qb_ipcs_service_t *s);
 204 bool pcmk__set_client_queue_max(pcmk__client_t *client, const char *qmax);
 205 
 206 int pcmk__ipc_send_ack_as(const char *function, int line, pcmk__client_t *c,
 207                           uint32_t request, uint32_t flags, const char *tag,
 208                           crm_exit_t status);
 209 #define pcmk__ipc_send_ack(c, req, flags, tag, st) \
 210     pcmk__ipc_send_ack_as(__func__, __LINE__, (c), (req), (flags), (tag), (st))
 211 
 212 int pcmk__ipc_prepare_iov(uint32_t request, xmlNode *message,
 213                           uint32_t max_send_size,
 214                           struct iovec **result, ssize_t *bytes);
 215 int pcmk__ipc_send_xml(pcmk__client_t *c, uint32_t request, xmlNode *message,
 216                        uint32_t flags);
 217 int pcmk__ipc_send_iov(pcmk__client_t *c, struct iovec *iov, uint32_t flags);
 218 xmlNode *pcmk__client_data2xml(pcmk__client_t *c, void *data,
 219                                uint32_t *id, uint32_t *flags);
 220 
 221 int pcmk__client_pid(qb_ipcs_connection_t *c);
 222 
 223 void pcmk__serve_attrd_ipc(qb_ipcs_service_t **ipcs,
 224                            struct qb_ipcs_service_handlers *cb);
 225 void pcmk__serve_fenced_ipc(qb_ipcs_service_t **ipcs,
 226                             struct qb_ipcs_service_handlers *cb);
 227 void pcmk__serve_pacemakerd_ipc(qb_ipcs_service_t **ipcs,
 228                                 struct qb_ipcs_service_handlers *cb);
 229 qb_ipcs_service_t *pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb);
 230 
 231 void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
 232                            qb_ipcs_service_t **ipcs_rw,
 233                            qb_ipcs_service_t **ipcs_shm,
 234                            struct qb_ipcs_service_handlers *ro_cb,
 235                            struct qb_ipcs_service_handlers *rw_cb);
 236 
 237 void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro,
 238         qb_ipcs_service_t *ipcs_rw,
 239         qb_ipcs_service_t *ipcs_shm);
 240 
 241 #ifdef __cplusplus
 242 }
 243 #endif
 244 
 245 #endif

/* [previous][next][first][last][top][bottom][index][help] */