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 #define REMOTE_AUTH_TIMEOUT 10000
  74 
  75 int num_clients;
  76 int authenticate_user(const char *user, const char *passwd);
  77 static int cib_remote_listen(gpointer data);
  78 static int cib_remote_msg(gpointer data);
  79 
  80 static void
  81 remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83     crm_info("No longer listening for remote connections");
  84     return;
  85 }
  86 
  87 int
  88 init_remote_listener(int port, gboolean encrypted)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     int rc;
  91     int *ssock = NULL;
  92     struct sockaddr_in saddr;
  93     int optval;
  94 
  95     static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
  96         .dispatch = cib_remote_listen,
  97         .destroy = remote_connection_destroy,
  98     };
  99 
 100     if (port <= 0) {
 101         /* don't start it */
 102         return 0;
 103     }
 104 
 105     if (encrypted) {
 106 #ifndef HAVE_GNUTLS_GNUTLS_H
 107         crm_warn("TLS support is not available");
 108         return 0;
 109 #else
 110         crm_notice("Starting TLS listener on port %d", port);
 111         crm_gnutls_global_init();
 112         /* gnutls_global_set_log_level (10); */
 113         gnutls_global_set_log_function(debug_log);
 114         if (pcmk__init_tls_dh(&dh_params) != pcmk_rc_ok) {
 115             return -1;
 116         }
 117         gnutls_anon_allocate_server_credentials(&anon_cred_s);
 118         gnutls_anon_set_server_dh_params(anon_cred_s, dh_params);
 119 #endif
 120     } else {
 121         crm_warn("Starting plain-text listener on port %d", port);
 122     }
 123 #ifndef HAVE_PAM
 124     crm_warn("PAM is _not_ enabled!");
 125 #endif
 126 
 127     /* create server socket */
 128     ssock = malloc(sizeof(int));
 129     if(ssock == NULL) {
 130         crm_err("Listener socket allocation failed: %s", pcmk_rc_str(errno));
 131         return -1;
 132     }
 133 
 134     *ssock = socket(AF_INET, SOCK_STREAM, 0);
 135     if (*ssock == -1) {
 136         crm_err("Listener socket creation failed: %s", pcmk_rc_str(errno));
 137         free(ssock);
 138         return -1;
 139     }
 140 
 141     /* reuse address */
 142     optval = 1;
 143     rc = setsockopt(*ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
 144     if (rc < 0) {
 145         crm_err("Local address reuse not allowed on listener socket: %s",
 146                 pcmk_rc_str(errno));
 147     }
 148 
 149     /* bind server socket */
 150     memset(&saddr, '\0', sizeof(saddr));
 151     saddr.sin_family = AF_INET;
 152     saddr.sin_addr.s_addr = INADDR_ANY;
 153     saddr.sin_port = htons(port);
 154     if (bind(*ssock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
 155         crm_err("Cannot bind to listener socket: %s", pcmk_rc_str(errno));
 156         close(*ssock);
 157         free(ssock);
 158         return -2;
 159     }
 160     if (listen(*ssock, 10) == -1) {
 161         crm_err("Cannot listen on socket: %s", pcmk_rc_str(errno));
 162         close(*ssock);
 163         free(ssock);
 164         return -3;
 165     }
 166 
 167     mainloop_add_fd("cib-remote", G_PRIORITY_DEFAULT, *ssock, ssock, &remote_listen_fd_callbacks);
 168     crm_debug("Started listener on port %d", port);
 169 
 170     return *ssock;
 171 }
 172 
 173 static int
 174 check_group_membership(const char *usr, const char *grp)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176     int index = 0;
 177     struct passwd *pwd = NULL;
 178     struct group *group = NULL;
 179 
 180     CRM_CHECK(usr != NULL, return FALSE);
 181     CRM_CHECK(grp != NULL, return FALSE);
 182 
 183     pwd = getpwnam(usr);
 184     if (pwd == NULL) {
 185         crm_err("No user named '%s' exists!", usr);
 186         return FALSE;
 187     }
 188 
 189     group = getgrgid(pwd->pw_gid);
 190     if (group != NULL && pcmk__str_eq(grp, group->gr_name, pcmk__str_none)) {
 191         return TRUE;
 192     }
 193 
 194     group = getgrnam(grp);
 195     if (group == NULL) {
 196         crm_err("No group named '%s' exists!", grp);
 197         return FALSE;
 198     }
 199 
 200     while (TRUE) {
 201         char *member = group->gr_mem[index++];
 202 
 203         if (member == NULL) {
 204             break;
 205 
 206         } else if (pcmk__str_eq(usr, member, pcmk__str_none)) {
 207             return TRUE;
 208         }
 209     };
 210 
 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     crm_log_xml_info(login, "Login: ");
 222     if (login == NULL) {
 223         return FALSE;
 224     }
 225 
 226     if (!pcmk__xe_is(login, PCMK__XE_CIB_COMMAND)) {
 227         crm_err("Unrecognizable message from remote client");
 228         crm_log_xml_info(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_err("Wrong operation: %s", tmp);
 235         return FALSE;
 236     }
 237 
 238     user = crm_element_value(login, PCMK_XA_USER);
 239     pass = crm_element_value(login, PCMK__XA_PASSWORD);
 240 
 241     if (!user || !pass) {
 242         crm_err("missing auth credentials");
 243         return FALSE;
 244     }
 245 
 246     /* Non-root daemons can only validate the password of the
 247      * user they're running as
 248      */
 249     if (check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) {
 250         crm_err("User is not a member of the required group");
 251         return FALSE;
 252 
 253     } else if (authenticate_user(user, pass) == FALSE) {
 254         crm_err("PAM auth failed");
 255         return FALSE;
 256     }
 257 
 258     return TRUE;
 259 }
 260 
 261 static gboolean
 262 remote_auth_timeout_cb(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264     pcmk__client_t *client = data;
 265 
 266     client->remote->auth_timeout = 0;
 267 
 268     if (pcmk_is_set(client->flags, pcmk__client_authenticated)) {
 269         return FALSE;
 270     }
 271 
 272     mainloop_del_fd(client->remote->source);
 273     crm_err("Remote client authentication timed out");
 274 
 275     return FALSE;
 276 }
 277 
 278 static int
 279 cib_remote_listen(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281     int csock = 0;
 282     unsigned laddr;
 283     struct sockaddr_storage addr;
 284     char ipstr[INET6_ADDRSTRLEN];
 285     int ssock = *(int *)data;
 286     int rc;
 287 
 288     pcmk__client_t *new_client = NULL;
 289 
 290     static struct mainloop_fd_callbacks remote_client_fd_callbacks = {
 291         .dispatch = cib_remote_msg,
 292         .destroy = cib_remote_connection_destroy,
 293     };
 294 
 295     /* accept the connection */
 296     laddr = sizeof(addr);
 297     memset(&addr, 0, sizeof(addr));
 298     csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
 299     if (csock == -1) {
 300         crm_err("Could not accept socket connection: %s", pcmk_rc_str(errno));
 301         return TRUE;
 302     }
 303 
 304     pcmk__sockaddr2str(&addr, ipstr);
 305     crm_debug("New %s connection from %s",
 306               ((ssock == remote_tls_fd)? "secure" : "clear-text"), ipstr);
 307 
 308     rc = pcmk__set_nonblocking(csock);
 309     if (rc != pcmk_rc_ok) {
 310         crm_err("Could not set socket non-blocking: %s " CRM_XS " rc=%d",
 311                 pcmk_rc_str(rc), rc);
 312         close(csock);
 313         return TRUE;
 314     }
 315 
 316     num_clients++;
 317 
 318     new_client = pcmk__new_unauth_client(NULL);
 319     new_client->remote = pcmk__assert_alloc(1, sizeof(pcmk__remote_t));
 320 
 321     if (ssock == remote_tls_fd) {
 322 #ifdef HAVE_GNUTLS_GNUTLS_H
 323         pcmk__set_client_flags(new_client, pcmk__client_tls);
 324 
 325         /* create gnutls session for the server socket */
 326         new_client->remote->tls_session = pcmk__new_tls_session(csock,
 327                                                                 GNUTLS_SERVER,
 328                                                                 GNUTLS_CRD_ANON,
 329                                                                 anon_cred_s);
 330         if (new_client->remote->tls_session == NULL) {
 331             close(csock);
 332             return TRUE;
 333         }
 334 #endif
 335     } else {
 336         pcmk__set_client_flags(new_client, pcmk__client_tcp);
 337         new_client->remote->tcp_socket = csock;
 338     }
 339 
 340     // Require the client to authenticate within this time
 341     new_client->remote->auth_timeout = g_timeout_add(REMOTE_AUTH_TIMEOUT,
 342                                                      remote_auth_timeout_cb,
 343                                                      new_client);
 344     crm_info("Remote CIB client pending authentication "
 345              CRM_XS " %p id: %s", new_client, new_client->id);
 346 
 347     new_client->remote->source =
 348         mainloop_add_fd("cib-remote-client", G_PRIORITY_DEFAULT, csock, new_client,
 349                         &remote_client_fd_callbacks);
 350 
 351     return TRUE;
 352 }
 353 
 354 void
 355 cib_remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357     pcmk__client_t *client = user_data;
 358     int csock = 0;
 359 
 360     if (client == NULL) {
 361         return;
 362     }
 363 
 364     crm_trace("Cleaning up after client %s disconnect",
 365               pcmk__client_name(client));
 366 
 367     num_clients--;
 368     crm_trace("Num unfree'd clients: %d", num_clients);
 369 
 370     switch (PCMK__CLIENT_TYPE(client)) {
 371         case pcmk__client_tcp:
 372             csock = client->remote->tcp_socket;
 373             break;
 374 #ifdef HAVE_GNUTLS_GNUTLS_H
 375         case pcmk__client_tls:
 376             if (client->remote->tls_session) {
 377                 void *sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session);
 378 
 379                 csock = GPOINTER_TO_INT(sock_ptr);
 380                 if (pcmk_is_set(client->flags,
 381                                 pcmk__client_tls_handshake_complete)) {
 382                     gnutls_bye(*client->remote->tls_session, GNUTLS_SHUT_WR);
 383                 }
 384                 gnutls_deinit(*client->remote->tls_session);
 385                 gnutls_free(client->remote->tls_session);
 386                 client->remote->tls_session = NULL;
 387             }
 388             break;
 389 #endif
 390         default:
 391             crm_warn("Unknown transport for client %s "
 392                      CRM_XS " flags=%#016" PRIx64,
 393                      pcmk__client_name(client), client->flags);
 394     }
 395 
 396     if (csock > 0) {
 397         close(csock);
 398     }
 399 
 400     pcmk__free_client(client);
 401 
 402     crm_trace("Freed the cib client");
 403 
 404     if (cib_shutdown_flag) {
 405         cib_shutdown(0);
 406     }
 407     return;
 408 }
 409 
 410 static void
 411 cib_handle_remote_msg(pcmk__client_t *client, xmlNode *command)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413     if (!pcmk__xe_is(command, PCMK__XE_CIB_COMMAND)) {
 414         crm_log_xml_trace(command, "bad");
 415         return;
 416     }
 417 
 418     if (client->name == NULL) {
 419         client->name = pcmk__str_copy(client->id);
 420     }
 421 
 422     /* unset dangerous options */
 423     pcmk__xe_remove_attr(command, PCMK__XA_SRC);
 424     pcmk__xe_remove_attr(command, PCMK__XA_CIB_HOST);
 425     pcmk__xe_remove_attr(command, PCMK__XA_CIB_UPDATE);
 426 
 427     crm_xml_add(command, PCMK__XA_T, PCMK__VALUE_CIB);
 428     crm_xml_add(command, PCMK__XA_CIB_CLIENTID, client->id);
 429     crm_xml_add(command, PCMK__XA_CIB_CLIENTNAME, client->name);
 430     crm_xml_add(command, PCMK__XA_CIB_USER, client->user);
 431 
 432     if (crm_element_value(command, PCMK__XA_CIB_CALLID) == NULL) {
 433         char *call_uuid = crm_generate_uuid();
 434 
 435         /* fix the command */
 436         crm_xml_add(command, PCMK__XA_CIB_CALLID, call_uuid);
 437         free(call_uuid);
 438     }
 439 
 440     if (crm_element_value(command, PCMK__XA_CIB_CALLOPT) == NULL) {
 441         crm_xml_add_int(command, PCMK__XA_CIB_CALLOPT, 0);
 442     }
 443 
 444     crm_log_xml_trace(command, "Remote command: ");
 445     cib_common_callback_worker(0, 0, command, client, TRUE);
 446 }
 447 
 448 static int
 449 cib_remote_msg(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451     xmlNode *command = NULL;
 452     pcmk__client_t *client = data;
 453     int rc;
 454     int timeout = 1000;
 455 
 456     if (pcmk_is_set(client->flags, pcmk__client_authenticated)) {
 457         timeout = -1;
 458     }
 459 
 460     crm_trace("Remote %s message received for client %s",
 461               pcmk__client_type_str(PCMK__CLIENT_TYPE(client)),
 462               pcmk__client_name(client));
 463 
 464 #ifdef HAVE_GNUTLS_GNUTLS_H
 465     if ((PCMK__CLIENT_TYPE(client) == pcmk__client_tls)
 466         && !pcmk_is_set(client->flags, pcmk__client_tls_handshake_complete)) {
 467 
 468         int rc = pcmk__read_handshake_data(client);
 469 
 470         if (rc == EAGAIN) {
 471             /* No more data is available at the moment. Just return for now;
 472              * we'll get invoked again once the client sends more.
 473              */
 474             return 0;
 475         } else if (rc != pcmk_rc_ok) {
 476             return -1;
 477         }
 478 
 479         crm_debug("TLS handshake with remote CIB client completed");
 480         pcmk__set_client_flags(client, pcmk__client_tls_handshake_complete);
 481         if (client->remote->auth_timeout) {
 482             g_source_remove(client->remote->auth_timeout);
 483         }
 484 
 485         // Require the client to authenticate within this time
 486         client->remote->auth_timeout = g_timeout_add(REMOTE_AUTH_TIMEOUT,
 487                                                      remote_auth_timeout_cb,
 488                                                      client);
 489         return 0;
 490     }
 491 #endif
 492 
 493     rc = pcmk__read_remote_message(client->remote, timeout);
 494 
 495     /* must pass auth before we will process anything else */
 496     if (!pcmk_is_set(client->flags, pcmk__client_authenticated)) {
 497         xmlNode *reg;
 498         const char *user = NULL;
 499 
 500         command = pcmk__remote_message_xml(client->remote);
 501         if (cib_remote_auth(command) == FALSE) {
 502             free_xml(command);
 503             return -1;
 504         }
 505 
 506         crm_notice("Remote CIB client connection accepted");
 507         pcmk__set_client_flags(client, pcmk__client_authenticated);
 508         g_source_remove(client->remote->auth_timeout);
 509         client->remote->auth_timeout = 0;
 510         client->name = crm_element_value_copy(command, PCMK_XA_NAME);
 511 
 512         user = crm_element_value(command, PCMK_XA_USER);
 513         if (user) {
 514             client->user = pcmk__str_copy(user);
 515         }
 516 
 517         /* send ACK */
 518         reg = pcmk__xe_create(NULL, PCMK__XE_CIB_RESULT);
 519         crm_xml_add(reg, PCMK__XA_CIB_OP, CRM_OP_REGISTER);
 520         crm_xml_add(reg, PCMK__XA_CIB_CLIENTID, client->id);
 521         pcmk__remote_send_xml(client->remote, reg);
 522         free_xml(reg);
 523         free_xml(command);
 524     }
 525 
 526     command = pcmk__remote_message_xml(client->remote);
 527     while (command) {
 528         crm_trace("Remote client message received");
 529         cib_handle_remote_msg(client, command);
 530         free_xml(command);
 531         command = pcmk__remote_message_xml(client->remote);
 532     }
 533 
 534     if (rc == ENOTCONN) {
 535         crm_trace("Remote CIB client disconnected while reading from it");
 536         return -1;
 537     }
 538 
 539     return 0;
 540 }
 541 
 542 #ifdef HAVE_PAM
 543 static int
 544 construct_pam_passwd(int num_msg, const struct pam_message **msg,
     /* [previous][next][first][last][top][bottom][index][help] */
 545                      struct pam_response **response, void *data)
 546 {
 547     int count = 0;
 548     struct pam_response *reply;
 549     char *string = (char *)data;
 550 
 551     CRM_CHECK(data, return PAM_CONV_ERR);
 552     CRM_CHECK(num_msg == 1, return PAM_CONV_ERR);       /* We only want to handle one message */
 553 
 554     reply = pcmk__assert_alloc(1, sizeof(struct pam_response));
 555 
 556     for (count = 0; count < num_msg; ++count) {
 557         switch (msg[count]->msg_style) {
 558             case PAM_TEXT_INFO:
 559                 crm_info("PAM: %s", msg[count]->msg);
 560                 break;
 561             case PAM_PROMPT_ECHO_OFF:
 562             case PAM_PROMPT_ECHO_ON:
 563                 reply[count].resp_retcode = 0;
 564                 reply[count].resp = string;     /* We already made a copy */
 565                 break;
 566             case PAM_ERROR_MSG:
 567                 /* In theory we'd want to print this, but then
 568                  * we see the password prompt in the logs
 569                  */
 570                 /* crm_err("PAM error: %s", msg[count]->msg); */
 571                 break;
 572             default:
 573                 crm_err("Unhandled conversation type: %d", msg[count]->msg_style);
 574                 goto bail;
 575         }
 576     }
 577 
 578     *response = reply;
 579     reply = NULL;
 580 
 581     return PAM_SUCCESS;
 582 
 583   bail:
 584     for (count = 0; count < num_msg; ++count) {
 585         if (reply[count].resp != NULL) {
 586             switch (msg[count]->msg_style) {
 587                 case PAM_PROMPT_ECHO_ON:
 588                 case PAM_PROMPT_ECHO_OFF:
 589                     /* Erase the data - it contained a password */
 590                     while (*(reply[count].resp)) {
 591                         *(reply[count].resp)++ = '\0';
 592                     }
 593                     free(reply[count].resp);
 594                     break;
 595             }
 596             reply[count].resp = NULL;
 597         }
 598     }
 599     free(reply);
 600     reply = NULL;
 601 
 602     return PAM_CONV_ERR;
 603 }
 604 #endif
 605 
 606 int
 607 authenticate_user(const char *user, const char *passwd)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609 #ifndef HAVE_PAM
 610     gboolean pass = TRUE;
 611 #else
 612     int rc = 0;
 613     gboolean pass = FALSE;
 614     const void *p_user = NULL;
 615 
 616     struct pam_conv p_conv;
 617     struct pam_handle *pam_h = NULL;
 618     static const char *pam_name = NULL;
 619 
 620     if (pam_name == NULL) {
 621         pam_name = getenv("CIB_pam_service");
 622     }
 623     if (pam_name == NULL) {
 624         pam_name = "login";
 625     }
 626 
 627     p_conv.conv = construct_pam_passwd;
 628     p_conv.appdata_ptr = pcmk__str_copy(passwd);
 629 
 630     rc = pam_start(pam_name, user, &p_conv, &pam_h);
 631     if (rc != PAM_SUCCESS) {
 632         crm_err("Could not initialize PAM: %s (%d)", pam_strerror(pam_h, rc), rc);
 633         goto bail;
 634     }
 635 
 636     rc = pam_authenticate(pam_h, 0);
 637     if (rc != PAM_SUCCESS) {
 638         crm_err("Authentication failed for %s: %s (%d)", user, pam_strerror(pam_h, rc), rc);
 639         goto bail;
 640     }
 641 
 642     /* Make sure we authenticated the user we wanted to authenticate.
 643      * Since we also run as non-root, it might be worth pre-checking
 644      * the user has the same EID as us, since that the only user we
 645      * can authenticate.
 646      */
 647     rc = pam_get_item(pam_h, PAM_USER, &p_user);
 648     if (rc != PAM_SUCCESS) {
 649         crm_err("Internal PAM error: %s (%d)", pam_strerror(pam_h, rc), rc);
 650         goto bail;
 651 
 652     } else if (p_user == NULL) {
 653         crm_err("Unknown user authenticated.");
 654         goto bail;
 655 
 656     } else if (!pcmk__str_eq(p_user, user, pcmk__str_casei)) {
 657         crm_err("User mismatch: %s vs. %s.", (const char *)p_user, (const char *)user);
 658         goto bail;
 659     }
 660 
 661     rc = pam_acct_mgmt(pam_h, 0);
 662     if (rc != PAM_SUCCESS) {
 663         crm_err("Access denied: %s (%d)", pam_strerror(pam_h, rc), rc);
 664         goto bail;
 665     }
 666     pass = TRUE;
 667 
 668   bail:
 669     pam_end(pam_h, rc);
 670 #endif
 671     return pass;
 672 }

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