root/daemons/based/based_remote.c

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

DEFINITIONS

This source file includes following definitions.
  1. debug_log
  2. remote_connection_destroy
  3. init_remote_listener
  4. check_group_membership
  5. cib_remote_auth
  6. remote_auth_timeout_cb
  7. cib_remote_listen
  8. cib_remote_connection_destroy
  9. cib_handle_remote_msg
  10. cib_remote_msg
  11. construct_pam_passwd
  12. authenticate_user

   1 /*
   2  * Copyright 2004-2024 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 General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 #include <crm/crm.h>
  12 
  13 #include <sys/param.h>
  14 #include <stdio.h>
  15 #include <sys/types.h>
  16 #include <sys/stat.h>
  17 #include <unistd.h>
  18 #include <inttypes.h>           // PRIx64
  19 #include <sys/socket.h>
  20 #include <arpa/inet.h>
  21 
  22 #include <netinet/ip.h>
  23 
  24 #include <stdlib.h>
  25 #include <errno.h>
  26 
  27 #include <glib.h>
  28 #include <libxml/tree.h>
  29 
  30 #include <crm/common/ipc.h>
  31 #include <crm/common/ipc_internal.h>
  32 #include <crm/common/xml.h>
  33 #include <crm/common/remote_internal.h>
  34 #include <crm/cib/internal.h>
  35 
  36 #include "pacemaker-based.h"
  37 
  38 /* #undef HAVE_PAM_PAM_APPL_H */
  39 /* #undef HAVE_GNUTLS_GNUTLS_H */
  40 
  41 #ifdef HAVE_GNUTLS_GNUTLS_H
  42 #  include <gnutls/gnutls.h>
  43 #endif
  44 
  45 #include <pwd.h>
  46 #include <grp.h>
  47 #if HAVE_SECURITY_PAM_APPL_H
  48 #  include <security/pam_appl.h>
  49 #  define HAVE_PAM 1
  50 #else
  51 #  if HAVE_PAM_PAM_APPL_H
  52 #    include <pam/pam_appl.h>
  53 #    define HAVE_PAM 1
  54 #  endif
  55 #endif
  56 
  57 extern int remote_tls_fd;
  58 extern gboolean cib_shutdown_flag;
  59 
  60 int init_remote_listener(int port, gboolean encrypted);
  61 void cib_remote_connection_destroy(gpointer user_data);
  62 
  63 #ifdef HAVE_GNUTLS_GNUTLS_H
  64 gnutls_dh_params_t dh_params;
  65 gnutls_anon_server_credentials_t anon_cred_s;
  66 static void
  67 debug_log(int level, const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69     fputs(str, stderr);
  70 }
  71 #endif
  72 
  73 // @TODO This is rather short for someone to type their password
  74 #define REMOTE_AUTH_TIMEOUT 10000
  75 
  76 int num_clients;
  77 static bool authenticate_user(const char *user, const char *passwd);
  78 static int cib_remote_listen(gpointer data);
  79 static int cib_remote_msg(gpointer data);
  80 
  81 static void
  82 remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84     crm_info("No longer listening for remote connections");
  85     return;
  86 }
  87 
  88 int
  89 init_remote_listener(int port, gboolean encrypted)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91     int rc;
  92     int *ssock = NULL;
  93     struct sockaddr_in saddr;
  94     int optval;
  95 
  96     static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
  97         .dispatch = cib_remote_listen,
  98         .destroy = remote_connection_destroy,
  99     };
 100 
 101     if (port <= 0) {
 102         /* don't start it */
 103         return 0;
 104     }
 105 
 106     if (encrypted) {
 107 #ifndef HAVE_GNUTLS_GNUTLS_H
 108         crm_warn("TLS support is not available");
 109         return 0;
 110 #else
 111         crm_notice("Starting TLS listener on port %d", port);
 112         crm_gnutls_global_init();
 113         /* gnutls_global_set_log_level (10); */
 114         gnutls_global_set_log_function(debug_log);
 115         if (pcmk__init_tls_dh(&dh_params) != pcmk_rc_ok) {
 116             return -1;
 117         }
 118         gnutls_anon_allocate_server_credentials(&anon_cred_s);
 119         gnutls_anon_set_server_dh_params(anon_cred_s, dh_params);
 120 #endif
 121     } else {
 122         crm_warn("Starting plain-text listener on port %d", port);
 123     }
 124 #ifndef HAVE_PAM
 125     crm_warn("PAM is _not_ enabled!");
 126 #endif
 127 
 128     /* create server socket */
 129     ssock = malloc(sizeof(int));
 130     if(ssock == NULL) {
 131         crm_err("Listener socket allocation failed: %s", pcmk_rc_str(errno));
 132         return -1;
 133     }
 134 
 135     *ssock = socket(AF_INET, SOCK_STREAM, 0);
 136     if (*ssock == -1) {
 137         crm_err("Listener socket creation failed: %s", pcmk_rc_str(errno));
 138         free(ssock);
 139         return -1;
 140     }
 141 
 142     /* reuse address */
 143     optval = 1;
 144     rc = setsockopt(*ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
 145     if (rc < 0) {
 146         crm_err("Local address reuse not allowed on listener socket: %s",
 147                 pcmk_rc_str(errno));
 148     }
 149 
 150     /* bind server socket */
 151     memset(&saddr, '\0', sizeof(saddr));
 152     saddr.sin_family = AF_INET;
 153     saddr.sin_addr.s_addr = INADDR_ANY;
 154     saddr.sin_port = htons(port);
 155     if (bind(*ssock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
 156         crm_err("Cannot bind to listener socket: %s", pcmk_rc_str(errno));
 157         close(*ssock);
 158         free(ssock);
 159         return -2;
 160     }
 161     if (listen(*ssock, 10) == -1) {
 162         crm_err("Cannot listen on socket: %s", pcmk_rc_str(errno));
 163         close(*ssock);
 164         free(ssock);
 165         return -3;
 166     }
 167 
 168     mainloop_add_fd("cib-remote", G_PRIORITY_DEFAULT, *ssock, ssock, &remote_listen_fd_callbacks);
 169     crm_debug("Started listener on port %d", port);
 170 
 171     return *ssock;
 172 }
 173 
 174 static int
 175 check_group_membership(const char *usr, const char *grp)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177     int index = 0;
 178     struct passwd *pwd = NULL;
 179     struct group *group = NULL;
 180 
 181     pwd = getpwnam(usr);
 182     if (pwd == NULL) {
 183         crm_notice("Rejecting remote client: '%s' is not a valid user", usr);
 184         return FALSE;
 185     }
 186 
 187     group = getgrgid(pwd->pw_gid);
 188     if (group != NULL && pcmk__str_eq(grp, group->gr_name, pcmk__str_none)) {
 189         return TRUE;
 190     }
 191 
 192     group = getgrnam(grp);
 193     if (group == NULL) {
 194         crm_err("Rejecting remote client: '%s' is not a valid group", grp);
 195         return FALSE;
 196     }
 197 
 198     while (TRUE) {
 199         char *member = group->gr_mem[index++];
 200 
 201         if (member == NULL) {
 202             break;
 203 
 204         } else if (pcmk__str_eq(usr, member, pcmk__str_none)) {
 205             return TRUE;
 206         }
 207     }
 208 
 209     crm_notice("Rejecting remote client: User '%s' is not a member of "
 210                "group '%s'", usr, grp);
 211     return FALSE;
 212 }
 213 
 214 static gboolean
 215 cib_remote_auth(xmlNode * login)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217     const char *user = NULL;
 218     const char *pass = NULL;
 219     const char *tmp = NULL;
 220 
 221     if (login == NULL) {
 222         return FALSE;
 223     }
 224 
 225     if (!pcmk__xe_is(login, PCMK__XE_CIB_COMMAND)) {
 226         crm_warn("Rejecting remote client: Unrecognizable message "
 227                  "(element '%s' not '" PCMK__XE_CIB_COMMAND "')", login->name);
 228         crm_log_xml_debug(login, "bad");
 229         return FALSE;
 230     }
 231 
 232     tmp = crm_element_value(login, PCMK_XA_OP);
 233     if (!pcmk__str_eq(tmp, "authenticate", pcmk__str_casei)) {
 234         crm_warn("Rejecting remote client: Unrecognizable message "
 235                  "(operation '%s' not 'authenticate')", tmp);
 236         crm_log_xml_debug(login, "bad");
 237         return FALSE;
 238     }
 239 
 240     user = crm_element_value(login, PCMK_XA_USER);
 241     pass = crm_element_value(login, PCMK__XA_PASSWORD);
 242     if (!user || !pass) {
 243         crm_warn("Rejecting remote client: No %s given",
 244                  ((user == NULL)? "username" : "password"));
 245         crm_log_xml_debug(login, "bad");
 246         return FALSE;
 247     }
 248 
 249     crm_log_xml_debug(login, "auth");
 250 
 251     return check_group_membership(user, CRM_DAEMON_GROUP)
 252            && authenticate_user(user, pass);
 253 }
 254 
 255 static gboolean
 256 remote_auth_timeout_cb(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258     pcmk__client_t *client = data;
 259 
 260     client->remote->auth_timeout = 0;
 261 
 262     if (pcmk_is_set(client->flags, pcmk__client_authenticated)) {
 263         return FALSE;
 264     }
 265 
 266     mainloop_del_fd(client->remote->source);
 267     crm_err("Remote client authentication timed out");
 268 
 269     return FALSE;
 270 }
 271 
 272 static int
 273 cib_remote_listen(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275     int csock = 0;
 276     unsigned laddr;
 277     struct sockaddr_storage addr;
 278     char ipstr[INET6_ADDRSTRLEN];
 279     int ssock = *(int *)data;
 280     int rc;
 281 
 282     pcmk__client_t *new_client = NULL;
 283 
 284     static struct mainloop_fd_callbacks remote_client_fd_callbacks = {
 285         .dispatch = cib_remote_msg,
 286         .destroy = cib_remote_connection_destroy,
 287     };
 288 
 289     /* accept the connection */
 290     laddr = sizeof(addr);
 291     memset(&addr, 0, sizeof(addr));
 292     csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
 293     if (csock == -1) {
 294         crm_warn("Could not accept remote connection: %s", pcmk_rc_str(errno));
 295         return TRUE;
 296     }
 297 
 298     pcmk__sockaddr2str(&addr, ipstr);
 299 
 300     rc = pcmk__set_nonblocking(csock);
 301     if (rc != pcmk_rc_ok) {
 302         crm_warn("Dropping remote connection from %s because "
 303                  "it could not be set to non-blocking: %s",
 304                  ipstr, pcmk_rc_str(rc));
 305         close(csock);
 306         return TRUE;
 307     }
 308 
 309     num_clients++;
 310 
 311     new_client = pcmk__new_unauth_client(NULL);
 312     new_client->remote = pcmk__assert_alloc(1, sizeof(pcmk__remote_t));
 313 
 314     if (ssock == remote_tls_fd) {
 315 #ifdef HAVE_GNUTLS_GNUTLS_H
 316         pcmk__set_client_flags(new_client, pcmk__client_tls);
 317 
 318         /* create gnutls session for the server socket */
 319         new_client->remote->tls_session = pcmk__new_tls_session(csock,
 320                                                                 GNUTLS_SERVER,
 321                                                                 GNUTLS_CRD_ANON,
 322                                                                 anon_cred_s);
 323         if (new_client->remote->tls_session == NULL) {
 324             close(csock);
 325             return TRUE;
 326         }
 327 #endif
 328     } else {
 329         pcmk__set_client_flags(new_client, pcmk__client_tcp);
 330         new_client->remote->tcp_socket = csock;
 331     }
 332 
 333     // Require the client to authenticate within this time
 334     new_client->remote->auth_timeout = g_timeout_add(REMOTE_AUTH_TIMEOUT,
 335                                                      remote_auth_timeout_cb,
 336                                                      new_client);
 337     crm_info("%s connection from %s pending authentication for client %s",
 338              ((ssock == remote_tls_fd)? "Encrypted" : "Clear-text"),
 339              ipstr, new_client->id);
 340 
 341     new_client->remote->source =
 342         mainloop_add_fd("cib-remote-client", G_PRIORITY_DEFAULT, csock, new_client,
 343                         &remote_client_fd_callbacks);
 344 
 345     return TRUE;
 346 }
 347 
 348 void
 349 cib_remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351     pcmk__client_t *client = user_data;
 352     int csock = 0;
 353 
 354     if (client == NULL) {
 355         return;
 356     }
 357 
 358     crm_trace("Cleaning up after client %s disconnect",
 359               pcmk__client_name(client));
 360 
 361     num_clients--;
 362     crm_trace("Num unfree'd clients: %d", num_clients);
 363 
 364     switch (PCMK__CLIENT_TYPE(client)) {
 365         case pcmk__client_tcp:
 366             csock = client->remote->tcp_socket;
 367             break;
 368 #ifdef HAVE_GNUTLS_GNUTLS_H
 369         case pcmk__client_tls:
 370             if (client->remote->tls_session) {
 371                 void *sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session);
 372 
 373                 csock = GPOINTER_TO_INT(sock_ptr);
 374                 if (pcmk_is_set(client->flags,
 375                                 pcmk__client_tls_handshake_complete)) {
 376                     gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_WR);
 377                 }
 378                 gnutls_deinit(*client->remote->tls_session);
 379                 gnutls_free(client->remote->tls_session);
 380                 client->remote->tls_session = NULL;
 381             }
 382             break;
 383 #endif
 384         default:
 385             crm_warn("Unknown transport for client %s "
 386                      CRM_XS " flags=%#016" PRIx64,
 387                      pcmk__client_name(client), client->flags);
 388     }
 389 
 390     if (csock > 0) {
 391         close(csock);
 392     }
 393 
 394     pcmk__free_client(client);
 395 
 396     crm_trace("Freed the cib client");
 397 
 398     if (cib_shutdown_flag) {
 399         cib_shutdown(0);
 400     }
 401     return;
 402 }
 403 
 404 static void
 405 cib_handle_remote_msg(pcmk__client_t *client, xmlNode *command)
     /* [previous][next][first][last][top][bottom][index][help] */
 406 {
 407     if (!pcmk__xe_is(command, PCMK__XE_CIB_COMMAND)) {
 408         crm_log_xml_trace(command, "bad");
 409         return;
 410     }
 411 
 412     if (client->name == NULL) {
 413         client->name = pcmk__str_copy(client->id);
 414     }
 415 
 416     /* unset dangerous options */
 417     pcmk__xe_remove_attr(command, PCMK__XA_SRC);
 418     pcmk__xe_remove_attr(command, PCMK__XA_CIB_HOST);
 419     pcmk__xe_remove_attr(command, PCMK__XA_CIB_UPDATE);
 420 
 421     crm_xml_add(command, PCMK__XA_T, PCMK__VALUE_CIB);
 422     crm_xml_add(command, PCMK__XA_CIB_CLIENTID, client->id);
 423     crm_xml_add(command, PCMK__XA_CIB_CLIENTNAME, client->name);
 424     crm_xml_add(command, PCMK__XA_CIB_USER, client->user);
 425 
 426     if (crm_element_value(command, PCMK__XA_CIB_CALLID) == NULL) {
 427         char *call_uuid = crm_generate_uuid();
 428 
 429         /* fix the command */
 430         crm_xml_add(command, PCMK__XA_CIB_CALLID, call_uuid);
 431         free(call_uuid);
 432     }
 433 
 434     if (crm_element_value(command, PCMK__XA_CIB_CALLOPT) == NULL) {
 435         crm_xml_add_int(command, PCMK__XA_CIB_CALLOPT, 0);
 436     }
 437 
 438     crm_log_xml_trace(command, "Remote command: ");
 439     cib_common_callback_worker(0, 0, command, client, TRUE);
 440 }
 441 
 442 static int
 443 cib_remote_msg(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445     xmlNode *command = NULL;
 446     pcmk__client_t *client = data;
 447     int rc;
 448     const char *client_name = pcmk__client_name(client);
 449 
 450     crm_trace("Remote %s message received for client %s",
 451               pcmk__client_type_str(PCMK__CLIENT_TYPE(client)), client_name);
 452 
 453 #ifdef HAVE_GNUTLS_GNUTLS_H
 454     if ((PCMK__CLIENT_TYPE(client) == pcmk__client_tls)
 455         && !pcmk_is_set(client->flags, pcmk__client_tls_handshake_complete)) {
 456 
 457         int rc = pcmk__read_handshake_data(client);
 458 
 459         if (rc == EAGAIN) {
 460             /* No more data is available at the moment. Just return for now;
 461              * we'll get invoked again once the client sends more.
 462              */
 463             return 0;
 464         } else if (rc != pcmk_rc_ok) {
 465             return -1;
 466         }
 467 
 468         crm_debug("Completed TLS handshake with remote client %s", client_name);
 469         pcmk__set_client_flags(client, pcmk__client_tls_handshake_complete);
 470         if (client->remote->auth_timeout) {
 471             g_source_remove(client->remote->auth_timeout);
 472         }
 473 
 474         // Require the client to authenticate within this time
 475         client->remote->auth_timeout = g_timeout_add(REMOTE_AUTH_TIMEOUT,
 476                                                      remote_auth_timeout_cb,
 477                                                      client);
 478         return 0;
 479     }
 480 #endif
 481 
 482     rc = pcmk__read_available_remote_data(client->remote);
 483     switch (rc) {
 484         case pcmk_rc_ok:
 485             break;
 486 
 487         case EAGAIN:
 488             /* We haven't read the whole message yet */
 489             return 0;
 490 
 491         default:
 492             /* Error */
 493             crm_trace("Error reading from remote client: %s", pcmk_rc_str(rc));
 494             return -1;
 495     }
 496 
 497     /* must pass auth before we will process anything else */
 498     if (!pcmk_is_set(client->flags, pcmk__client_authenticated)) {
 499         xmlNode *reg;
 500         const char *user = NULL;
 501 
 502         command = pcmk__remote_message_xml(client->remote);
 503         if (cib_remote_auth(command) == FALSE) {
 504             free_xml(command);
 505             return -1;
 506         }
 507 
 508         pcmk__set_client_flags(client, pcmk__client_authenticated);
 509         g_source_remove(client->remote->auth_timeout);
 510         client->remote->auth_timeout = 0;
 511         client->name = crm_element_value_copy(command, PCMK_XA_NAME);
 512 
 513         user = crm_element_value(command, PCMK_XA_USER);
 514         if (user) {
 515             client->user = pcmk__str_copy(user);
 516         }
 517 
 518         crm_notice("Remote connection accepted for authenticated user %s "
 519                    CRM_XS " client %s",
 520                    pcmk__s(user, ""), client_name);
 521 
 522         /* send ACK */
 523         reg = pcmk__xe_create(NULL, PCMK__XE_CIB_RESULT);
 524         crm_xml_add(reg, PCMK__XA_CIB_OP, CRM_OP_REGISTER);
 525         crm_xml_add(reg, PCMK__XA_CIB_CLIENTID, client->id);
 526         pcmk__remote_send_xml(client->remote, reg);
 527         free_xml(reg);
 528         free_xml(command);
 529     }
 530 
 531     command = pcmk__remote_message_xml(client->remote);
 532     if (command != NULL) {
 533         crm_trace("Remote message received from client %s", client_name);
 534         cib_handle_remote_msg(client, command);
 535         free_xml(command);
 536     }
 537 
 538     return 0;
 539 }
 540 
 541 #ifdef HAVE_PAM
 542 /*!
 543  * \internal
 544  * \brief Pass remote user's password to PAM
 545  *
 546  * \param[in]  num_msg   Number of entries in \p msg
 547  * \param[in]  msg       Array of PAM messages
 548  * \param[out] response  Where to set response to PAM
 549  * \param[in]  data      User data (the password string)
 550  *
 551  * \return PAM return code (PAM_BUF_ERR for memory errors, PAM_CONV_ERR for all
 552  *         other errors, or PAM_SUCCESS on success)
 553  * \note See pam_conv(3) for more explanation
 554  */
 555 static int
 556 construct_pam_passwd(int num_msg, const struct pam_message **msg,
     /* [previous][next][first][last][top][bottom][index][help] */
 557                      struct pam_response **response, void *data)
 558 {
 559     /* In theory, multiple messages are allowed, but due to OS compatibility
 560      * issues, PAM implementations are recommended to only send one message at a
 561      * time. We can require that here for simplicity.
 562      */
 563     CRM_CHECK((num_msg == 1) && (msg != NULL) && (response != NULL)
 564               && (data != NULL), return PAM_CONV_ERR);
 565 
 566     switch (msg[0]->msg_style) {
 567         case PAM_PROMPT_ECHO_OFF:
 568         case PAM_PROMPT_ECHO_ON:
 569             // Password requested
 570             break;
 571         case PAM_TEXT_INFO:
 572             crm_info("PAM: %s", msg[0]->msg);
 573             data = NULL;
 574             break;
 575         case PAM_ERROR_MSG:
 576             /* In theory we should show msg[0]->msg, but that might
 577              * contain the password, which we don't want in the logs
 578              */
 579             crm_err("PAM reported an error");
 580             data = NULL;
 581             break;
 582         default:
 583             crm_warn("Ignoring PAM message of unrecognized type %d",
 584                      msg[0]->msg_style);
 585             return PAM_CONV_ERR;
 586     }
 587 
 588     *response = calloc(1, sizeof(struct pam_response));
 589     if (*response == NULL) {
 590         return PAM_BUF_ERR;
 591     }
 592     (*response)->resp_retcode = 0;
 593     (*response)->resp = pcmk__str_copy((const char *) data); // Caller will free
 594     return PAM_SUCCESS;
 595 }
 596 #endif
 597 
 598 /*!
 599  * \internal
 600  * \brief Verify the username and password passed for a remote CIB connection
 601  *
 602  * \param[in] user    Username passed for remote CIB connection
 603  * \param[in] passwd  Password passed for remote CIB connection
 604  *
 605  * \return \c true if the username and password are accepted, otherwise \c false
 606  * \note This function accepts any username and password when built without PAM
 607  *       support.
 608  */
 609 static bool
 610 authenticate_user(const char *user, const char *passwd)
     /* [previous][next][first][last][top][bottom][index][help] */
 611 {
 612 #ifdef HAVE_PAM
 613     int rc = 0;
 614     bool pass = false;
 615     const void *p_user = NULL;
 616     struct pam_conv p_conv;
 617     struct pam_handle *pam_h = NULL;
 618 
 619     static const char *pam_name = NULL;
 620 
 621     if (pam_name == NULL) {
 622         pam_name = getenv("CIB_pam_service");
 623         if (pam_name == NULL) {
 624             pam_name = "login";
 625         }
 626     }
 627 
 628     p_conv.conv = construct_pam_passwd;
 629     p_conv.appdata_ptr = (void *) passwd;
 630 
 631     rc = pam_start(pam_name, user, &p_conv, &pam_h);
 632     if (rc != PAM_SUCCESS) {
 633         crm_warn("Rejecting remote client for user %s "
 634                  "because PAM initialization failed: %s",
 635                  user, pam_strerror(pam_h, rc));
 636         goto bail;
 637     }
 638 
 639     // Check user credentials
 640     rc = pam_authenticate(pam_h, PAM_SILENT);
 641     if (rc != PAM_SUCCESS) {
 642         crm_notice("Access for remote user %s denied: %s",
 643                    user, pam_strerror(pam_h, rc));
 644         goto bail;
 645     }
 646 
 647     /* Get the authenticated user name (PAM modules can map the original name to
 648      * something else). Since the CIB manager runs as the daemon user (not
 649      * root), that is the only user that can be successfully authenticated.
 650      */
 651     rc = pam_get_item(pam_h, PAM_USER, &p_user);
 652     if (rc != PAM_SUCCESS) {
 653         crm_warn("Rejecting remote client for user %s "
 654                  "because PAM failed to return final user name: %s",
 655                  user, pam_strerror(pam_h, rc));
 656         goto bail;
 657     }
 658     if (p_user == NULL) {
 659         crm_warn("Rejecting remote client for user %s "
 660                  "because PAM returned no final user name", user);
 661         goto bail;
 662     }
 663 
 664     // @TODO Why do we require these to match?
 665     if (!pcmk__str_eq(p_user, user, pcmk__str_none)) {
 666         crm_warn("Rejecting remote client for user %s "
 667                  "because PAM returned different final user name %s",
 668                  user, p_user);
 669         goto bail;
 670     }
 671 
 672     // Check user account restrictions (expiration, etc.)
 673     rc = pam_acct_mgmt(pam_h, PAM_SILENT);
 674     if (rc != PAM_SUCCESS) {
 675         crm_notice("Access for remote user %s denied: %s",
 676                    user, pam_strerror(pam_h, rc));
 677         goto bail;
 678     }
 679     pass = true;
 680 
 681 bail:
 682     pam_end(pam_h, rc);
 683     return pass;
 684 #else
 685     // @TODO Implement for non-PAM environments
 686     return true;
 687 #endif
 688 }

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