root/include/crm/common/ipc_internal.h

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

INCLUDED FROM


   1 /*
   2  * Copyright 2013-2020 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 #if defined(US_AUTH_GETPEEREID)
  44 /* on FreeBSD, we don't want to expose "non-yieldable PID" (leading to
  45    "IPC liveness check only") as its nominal representation, which could
  46    cause confusion -- this is unambiguous as long as there's no
  47    socket-based activation like with systemd (very improbable) */
  48 #define PCMK__SPECIAL_PID_AS_0(p)  (((p) == PCMK__SPECIAL_PID) ? 0 : (p))
  49 #else
  50 #define PCMK__SPECIAL_PID_AS_0(p)  (p)
  51 #endif
  52 
  53 /*!
  54  * \internal
  55  * \brief Check the authenticity and liveness of the process via IPC end-point
  56  *
  57  * When IPC daemon under given IPC end-point (name) detected, its authenticity
  58  * is verified by the means of comparing against provided referential UID and
  59  * GID, and the result of this check can be deduced from the return value.
  60  * As an exception, referential UID of 0 (~ root) satisfies arbitrary
  61  * detected daemon's credentials.
  62  *
  63  * \param[in]  name    IPC name to base the search on
  64  * \param[in]  refuid  referential UID to check against
  65  * \param[in]  refgid  referential GID to check against
  66  * \param[out] gotpid  to optionally store obtained PID of the found process
  67  *                     upon returning 1 or -2
  68  *                     (not available on FreeBSD, special value of 1,
  69  *                     see PCMK__SPECIAL_PID, used instead, and the caller
  70  *                     is required to special case this value respectively)
  71  *
  72  * \return Standard Pacemaker return code
  73  *
  74  * \note Return codes of particular interest include pcmk_rc_ipc_unresponsive
  75  *       indicating that no trace of IPC liveness was detected, and
  76  *       pcmk_rc_ipc_unauthorized indicating that the IPC endpoint is blocked by
  77  *       an unauthorized process.
  78  * \note This function emits a log message for return codes other than
  79  *       pcmk_rc_ok and pcmk_rc_ipc_unresponsive, and when there isn't a perfect
  80  *       match in respect to \p reguid and/or \p refgid, for a possible
  81  *       least privilege principle violation.
  82  *
  83  * \see crm_ipc_is_authentic_process
  84  */
  85 int pcmk__ipc_is_authentic_process_active(const char *name, uid_t refuid,
  86                                           gid_t refgid, pid_t *gotpid);
  87 
  88 
  89 /*
  90  * Server-related
  91  */
  92 
  93 typedef struct pcmk__client_s pcmk__client_t;
  94 
  95 struct pcmk__remote_s {
  96     /* Shared */
  97     char *buffer;
  98     size_t buffer_size;
  99     size_t buffer_offset;
 100     int auth_timeout;
 101     int tcp_socket;
 102     mainloop_io_t *source;
 103 
 104     /* CIB-only */
 105     bool authenticated;
 106     char *token;
 107 
 108     /* TLS only */
 109 #  ifdef HAVE_GNUTLS_GNUTLS_H
 110     gnutls_session_t *tls_session;
 111     bool tls_handshake_complete;
 112 #  endif
 113 };
 114 
 115 enum pcmk__client_flags {
 116     // Lower 32 bits are reserved for server (not library) use
 117 
 118     // Next 8 bits are reserved for client type (sort of a cheap enum)
 119     pcmk__client_ipc        = (UINT64_C(1) << 32), // Client uses plain IPC
 120     pcmk__client_tcp        = (UINT64_C(1) << 33), // Client uses TCP connection
 121 #  ifdef HAVE_GNUTLS_GNUTLS_H
 122     pcmk__client_tls        = (UINT64_C(1) << 34), // Client uses TCP with TLS
 123 #  endif
 124 
 125     // The rest are client attributes
 126     pcmk__client_proxied    = (UINT64_C(1) << 40), // Client IPC is proxied
 127     pcmk__client_privileged = (UINT64_C(1) << 41), // root or cluster user
 128     pcmk__client_to_proxy   = (UINT64_C(1) << 42), // Local client to be proxied
 129 };
 130 
 131 #define PCMK__CLIENT_TYPE(client) ((client)->flags & UINT64_C(0xff00000000))
 132 
 133 struct pcmk__client_s {
 134     unsigned int pid;
 135 
 136     uid_t uid;
 137     gid_t gid;
 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", ((client)->name? (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", ((client)->name? (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 qb_ipcs_service_t *pcmk__serve_controld_ipc(struct qb_ipcs_service_handlers *cb);
 228 
 229 void pcmk__serve_based_ipc(qb_ipcs_service_t **ipcs_ro,
 230                            qb_ipcs_service_t **ipcs_rw,
 231                            qb_ipcs_service_t **ipcs_shm,
 232                            struct qb_ipcs_service_handlers *ro_cb,
 233                            struct qb_ipcs_service_handlers *rw_cb);
 234 
 235 void pcmk__stop_based_ipc(qb_ipcs_service_t *ipcs_ro,
 236         qb_ipcs_service_t *ipcs_rw,
 237         qb_ipcs_service_t *ipcs_shm);
 238 
 239 #ifdef __cplusplus
 240 }
 241 #endif
 242 
 243 #endif

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