root/cib/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 (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  *
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 
  19 #include <crm_internal.h>
  20 #include <crm/crm.h>
  21 
  22 #include <sys/param.h>
  23 #include <stdio.h>
  24 #include <sys/types.h>
  25 #include <sys/stat.h>
  26 #include <unistd.h>
  27 #include <sys/socket.h>
  28 #include <arpa/inet.h>
  29 
  30 #include <netinet/ip.h>
  31 
  32 #include <stdlib.h>
  33 #include <errno.h>
  34 #include <glib.h>
  35 
  36 #include <crm/msg_xml.h>
  37 #include <crm/common/ipc.h>
  38 #include <crm/common/ipcs.h>
  39 #include <crm/common/xml.h>
  40 #include <crm/cib/internal.h>
  41 
  42 #include "callbacks.h"
  43 /* #undef HAVE_PAM_PAM_APPL_H */
  44 /* #undef HAVE_GNUTLS_GNUTLS_H */
  45 
  46 #ifdef HAVE_GNUTLS_GNUTLS_H
  47 #  undef KEYFILE
  48 #  include <gnutls/gnutls.h>
  49 #endif
  50 
  51 #include <pwd.h>
  52 #include <grp.h>
  53 #if HAVE_SECURITY_PAM_APPL_H
  54 #  include <security/pam_appl.h>
  55 #  define HAVE_PAM 1
  56 #else
  57 #  if HAVE_PAM_PAM_APPL_H
  58 #    include <pam/pam_appl.h>
  59 #    define HAVE_PAM 1
  60 #  endif
  61 #endif
  62 
  63 extern int remote_tls_fd;
  64 extern gboolean cib_shutdown_flag;
  65 
  66 int init_remote_listener(int port, gboolean encrypted);
  67 void cib_remote_connection_destroy(gpointer user_data);
  68 
  69 #ifdef HAVE_GNUTLS_GNUTLS_H
  70 #  define DH_BITS 1024
  71 gnutls_dh_params_t dh_params;
  72 gnutls_anon_server_credentials_t anon_cred_s;
  73 static void
  74 debug_log(int level, const char *str)
     /* [previous][next][first][last][top][bottom][index][help] */
  75 {
  76     fputs(str, stderr);
  77 }
  78 #endif
  79 
  80 #define REMOTE_AUTH_TIMEOUT 10000
  81 
  82 int num_clients;
  83 int authenticate_user(const char *user, const char *passwd);
  84 int cib_remote_listen(gpointer data);
  85 int cib_remote_msg(gpointer data);
  86 
  87 static void
  88 remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     return;
  91 }
  92 
  93 #define ERROR_SUFFIX "  Shutting down remote listener"
  94 int
  95 init_remote_listener(int port, gboolean encrypted)
     /* [previous][next][first][last][top][bottom][index][help] */
  96 {
  97     int rc;
  98     int *ssock = NULL;
  99     struct sockaddr_in saddr;
 100     int optval;
 101 
 102     static struct mainloop_fd_callbacks remote_listen_fd_callbacks = {
 103         .dispatch = cib_remote_listen,
 104         .destroy = remote_connection_destroy,
 105     };
 106 
 107     if (port <= 0) {
 108         /* don't start it */
 109         return 0;
 110     }
 111 
 112     if (encrypted) {
 113 #ifndef HAVE_GNUTLS_GNUTLS_H
 114         crm_warn("TLS support is not available");
 115         return 0;
 116 #else
 117         crm_notice("Starting a tls listener on port %d.", port);
 118         crm_gnutls_global_init();
 119         /* gnutls_global_set_log_level (10); */
 120         gnutls_global_set_log_function(debug_log);
 121         gnutls_dh_params_init(&dh_params);
 122         gnutls_dh_params_generate2(dh_params, DH_BITS);
 123         gnutls_anon_allocate_server_credentials(&anon_cred_s);
 124         gnutls_anon_set_server_dh_params(anon_cred_s, dh_params);
 125 #endif
 126     } else {
 127         crm_warn("Starting a plain_text listener on port %d.", port);
 128     }
 129 #ifndef HAVE_PAM
 130     crm_warn("PAM is _not_ enabled!");
 131 #endif
 132 
 133     /* create server socket */
 134     ssock = malloc(sizeof(int));
 135     if(ssock == NULL) {
 136         crm_perror(LOG_ERR, "Can not create server socket." ERROR_SUFFIX);
 137         return -1;
 138     }
 139 
 140     *ssock = socket(AF_INET, SOCK_STREAM, 0);
 141     if (*ssock == -1) {
 142         crm_perror(LOG_ERR, "Can not create server socket." ERROR_SUFFIX);
 143         free(ssock);
 144         return -1;
 145     }
 146 
 147     /* reuse address */
 148     optval = 1;
 149     rc = setsockopt(*ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
 150     if (rc < 0) {
 151         crm_perror(LOG_INFO, "Couldn't allow the reuse of local addresses by our remote listener");
 152     }
 153 
 154     /* bind server socket */
 155     memset(&saddr, '\0', sizeof(saddr));
 156     saddr.sin_family = AF_INET;
 157     saddr.sin_addr.s_addr = INADDR_ANY;
 158     saddr.sin_port = htons(port);
 159     if (bind(*ssock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
 160         crm_perror(LOG_ERR, "Can not bind server socket." ERROR_SUFFIX);
 161         close(*ssock);
 162         free(ssock);
 163         return -2;
 164     }
 165     if (listen(*ssock, 10) == -1) {
 166         crm_perror(LOG_ERR, "Can not start listen." ERROR_SUFFIX);
 167         close(*ssock);
 168         free(ssock);
 169         return -3;
 170     }
 171 
 172     mainloop_add_fd("cib-remote", G_PRIORITY_DEFAULT, *ssock, ssock, &remote_listen_fd_callbacks);
 173 
 174     return *ssock;
 175 }
 176 
 177 static int
 178 check_group_membership(const char *usr, const char *grp)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180     int index = 0;
 181     struct passwd *pwd = NULL;
 182     struct group *group = NULL;
 183 
 184     CRM_CHECK(usr != NULL, return FALSE);
 185     CRM_CHECK(grp != NULL, return FALSE);
 186 
 187     pwd = getpwnam(usr);
 188     if (pwd == NULL) {
 189         crm_err("No user named '%s' exists!", usr);
 190         return FALSE;
 191     }
 192 
 193     group = getgrgid(pwd->pw_gid);
 194     if (group != NULL && crm_str_eq(grp, group->gr_name, TRUE)) {
 195         return TRUE;
 196     }
 197 
 198     group = getgrnam(grp);
 199     if (group == NULL) {
 200         crm_err("No group named '%s' exists!", grp);
 201         return FALSE;
 202     }
 203 
 204     while (TRUE) {
 205         char *member = group->gr_mem[index++];
 206 
 207         if (member == NULL) {
 208             break;
 209 
 210         } else if (crm_str_eq(usr, member, TRUE)) {
 211             return TRUE;
 212         }
 213     };
 214 
 215     return FALSE;
 216 }
 217 
 218 static gboolean
 219 cib_remote_auth(xmlNode * login)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221     const char *user = NULL;
 222     const char *pass = NULL;
 223     const char *tmp = NULL;
 224 
 225     crm_log_xml_info(login, "Login: ");
 226     if (login == NULL) {
 227         return FALSE;
 228     }
 229 
 230     tmp = crm_element_name(login);
 231     if (safe_str_neq(tmp, "cib_command")) {
 232         crm_err("Wrong tag: %s", tmp);
 233         return FALSE;
 234     }
 235 
 236     tmp = crm_element_value(login, "op");
 237     if (safe_str_neq(tmp, "authenticate")) {
 238         crm_err("Wrong operation: %s", tmp);
 239         return FALSE;
 240     }
 241 
 242     user = crm_element_value(login, "user");
 243     pass = crm_element_value(login, "password");
 244 
 245     if (!user || !pass) {
 246         crm_err("missing auth credentials");
 247         return FALSE;
 248     }
 249 
 250     /* Non-root daemons can only validate the password of the
 251      * user they're running as
 252      */
 253     if (check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) {
 254         crm_err("User is not a member of the required group");
 255         return FALSE;
 256 
 257     } else if (authenticate_user(user, pass) == FALSE) {
 258         crm_err("PAM auth failed");
 259         return FALSE;
 260     }
 261 
 262     return TRUE;
 263 }
 264 
 265 static gboolean
 266 remote_auth_timeout_cb(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 267 {
 268     crm_client_t *client = data;
 269 
 270     client->remote->auth_timeout = 0;
 271 
 272     if (client->remote->authenticated == TRUE) {
 273         return FALSE;
 274     }
 275 
 276     mainloop_del_fd(client->remote->source);
 277     crm_err("Remote client authentication timed out");
 278 
 279     return FALSE;
 280 }
 281 
 282 int
 283 cib_remote_listen(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285     int csock = 0;
 286     unsigned laddr;
 287     struct sockaddr_storage addr;
 288     char ipstr[INET6_ADDRSTRLEN];
 289     int ssock = *(int *)data;
 290     int rc;
 291 
 292     crm_client_t *new_client = NULL;
 293 
 294     static struct mainloop_fd_callbacks remote_client_fd_callbacks = {
 295         .dispatch = cib_remote_msg,
 296         .destroy = cib_remote_connection_destroy,
 297     };
 298 
 299     /* accept the connection */
 300     laddr = sizeof(addr);
 301     memset(&addr, 0, sizeof(addr));
 302     csock = accept(ssock, (struct sockaddr *)&addr, &laddr);
 303     if (csock == -1) {
 304         crm_perror(LOG_ERR, "Could not accept socket connection");
 305         return TRUE;
 306     }
 307 
 308     crm_sockaddr2str(&addr, ipstr);
 309     crm_debug("New %s connection from %s",
 310               ((ssock == remote_tls_fd)? "secure" : "clear-text"), ipstr);
 311 
 312     rc = crm_set_nonblocking(csock);
 313     if (rc < 0) {
 314         crm_err("Could not set socket non-blocking: %s " CRM_XS " rc=%d",
 315                 pcmk_strerror(rc), rc);
 316         close(csock);
 317         return TRUE;
 318     }
 319 
 320     num_clients++;
 321 
 322     crm_client_init();
 323     new_client = crm_client_alloc(NULL);
 324     new_client->remote = calloc(1, sizeof(crm_remote_t));
 325 
 326     if (ssock == remote_tls_fd) {
 327 #ifdef HAVE_GNUTLS_GNUTLS_H
 328         new_client->kind = CRM_CLIENT_TLS;
 329 
 330         /* create gnutls session for the server socket */
 331         new_client->remote->tls_session =
 332             crm_create_anon_tls_session(csock, GNUTLS_SERVER, anon_cred_s);
 333 
 334         if (new_client->remote->tls_session == NULL) {
 335             crm_err("TLS session creation failed");
 336             close(csock);
 337             return TRUE;
 338         }
 339 #endif
 340     } else {
 341         new_client->kind = CRM_CLIENT_TCP;
 342         new_client->remote->tcp_socket = csock;
 343     }
 344 
 345     /* clients have a few seconds to perform handshake. */
 346     new_client->remote->auth_timeout =
 347         g_timeout_add(REMOTE_AUTH_TIMEOUT, remote_auth_timeout_cb, new_client);
 348 
 349     new_client->remote->source =
 350         mainloop_add_fd("cib-remote-client", G_PRIORITY_DEFAULT, csock, new_client,
 351                         &remote_client_fd_callbacks);
 352 
 353     return TRUE;
 354 }
 355 
 356 void
 357 cib_remote_connection_destroy(gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359     crm_client_t *client = user_data;
 360     int csock = 0;
 361 
 362     if (client == NULL) {
 363         return;
 364     }
 365 
 366     crm_trace("Cleaning up after client disconnect: %s/%s", crm_str(client->name), client->id);
 367 
 368     num_clients--;
 369     crm_trace("Num unfree'd clients: %d", num_clients);
 370 
 371     switch (client->kind) {
 372         case CRM_CLIENT_TCP:
 373             csock = client->remote->tcp_socket;
 374             break;
 375 #ifdef HAVE_GNUTLS_GNUTLS_H
 376         case CRM_CLIENT_TLS:
 377             if (client->remote->tls_session) {
 378                 void *sock_ptr = gnutls_transport_get_ptr(*client->remote->tls_session);
 379 
 380                 csock = GPOINTER_TO_INT(sock_ptr);
 381                 if (client->remote->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("Unexpected client type %d", client->kind);
 392     }
 393 
 394     if (csock > 0) {
 395         close(csock);
 396     }
 397 
 398     crm_client_destroy(client);
 399 
 400     crm_trace("Freed the cib client");
 401 
 402     if (cib_shutdown_flag) {
 403         cib_shutdown(0);
 404     }
 405     return;
 406 }
 407 
 408 static void
 409 cib_handle_remote_msg(crm_client_t * client, xmlNode * command)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411     const char *value = NULL;
 412 
 413     value = crm_element_name(command);
 414     if (safe_str_neq(value, "cib_command")) {
 415         crm_log_xml_trace(command, "Bad command: ");
 416         return;
 417     }
 418 
 419     if (client->name == NULL) {
 420         value = crm_element_value(command, F_CLIENTNAME);
 421         if (value == NULL) {
 422             client->name = strdup(client->id);
 423         } else {
 424             client->name = strdup(value);
 425         }
 426     }
 427 
 428     if (client->userdata == NULL) {
 429         value = crm_element_value(command, F_CIB_CALLBACK_TOKEN);
 430         if (value != NULL) {
 431             client->userdata = strdup(value);
 432             crm_trace("Callback channel for %s is %s", client->id, (char*)client->userdata);
 433 
 434         } else {
 435             client->userdata = strdup(client->id);
 436         }
 437     }
 438 
 439     /* unset dangerous options */
 440     xml_remove_prop(command, F_ORIG);
 441     xml_remove_prop(command, F_CIB_HOST);
 442     xml_remove_prop(command, F_CIB_GLOBAL_UPDATE);
 443 
 444     crm_xml_add(command, F_TYPE, T_CIB);
 445     crm_xml_add(command, F_CIB_CLIENTID, client->id);
 446     crm_xml_add(command, F_CIB_CLIENTNAME, client->name);
 447 #if ENABLE_ACL
 448     crm_xml_add(command, F_CIB_USER, client->user);
 449 #endif
 450 
 451     if (crm_element_value(command, F_CIB_CALLID) == NULL) {
 452         char *call_uuid = crm_generate_uuid();
 453 
 454         /* fix the command */
 455         crm_xml_add(command, F_CIB_CALLID, call_uuid);
 456         free(call_uuid);
 457     }
 458 
 459     if (crm_element_value(command, F_CIB_CALLOPTS) == NULL) {
 460         crm_xml_add_int(command, F_CIB_CALLOPTS, 0);
 461     }
 462 
 463     crm_log_xml_trace(command, "Remote command: ");
 464     cib_common_callback_worker(0, 0, command, client, TRUE);
 465 }
 466 
 467 int
 468 cib_remote_msg(gpointer data)
     /* [previous][next][first][last][top][bottom][index][help] */
 469 {
 470     xmlNode *command = NULL;
 471     crm_client_t *client = data;
 472     int disconnected = 0;
 473     int timeout = client->remote->authenticated ? -1 : 1000;
 474 
 475     crm_trace("%s callback", client->kind != CRM_CLIENT_TCP ? "secure" : "clear-text");
 476 
 477 #ifdef HAVE_GNUTLS_GNUTLS_H
 478     if (client->kind == CRM_CLIENT_TLS && (client->remote->tls_handshake_complete == FALSE)) {
 479         int rc = 0;
 480 
 481         /* Muliple calls to handshake will be required, this callback
 482          * will be invoked once the client sends more handshake data. */
 483         do {
 484             rc = gnutls_handshake(*client->remote->tls_session);
 485 
 486             if (rc < 0 && rc != GNUTLS_E_AGAIN) {
 487                 crm_err("Remote cib tls handshake failed");
 488                 return -1;
 489             }
 490         } while (rc == GNUTLS_E_INTERRUPTED);
 491 
 492         if (rc == 0) {
 493             crm_debug("Remote cib tls handshake completed");
 494             client->remote->tls_handshake_complete = TRUE;
 495             if (client->remote->auth_timeout) {
 496                 g_source_remove(client->remote->auth_timeout);
 497             }
 498             /* after handshake, clients must send auth in a few seconds */
 499             client->remote->auth_timeout =
 500                 g_timeout_add(REMOTE_AUTH_TIMEOUT, remote_auth_timeout_cb, client);
 501         }
 502         return 0;
 503     }
 504 #endif
 505 
 506     crm_remote_recv(client->remote, timeout, &disconnected);
 507 
 508     /* must pass auth before we will process anything else */
 509     if (client->remote->authenticated == FALSE) {
 510         xmlNode *reg;
 511 
 512 #if ENABLE_ACL
 513         const char *user = NULL;
 514 #endif
 515         command = crm_remote_parse_buffer(client->remote);
 516         if (cib_remote_auth(command) == FALSE) {
 517             free_xml(command);
 518             return -1;
 519         }
 520 
 521         crm_debug("remote connection authenticated successfully");
 522         client->remote->authenticated = TRUE;
 523         g_source_remove(client->remote->auth_timeout);
 524         client->remote->auth_timeout = 0;
 525         client->name = crm_element_value_copy(command, "name");
 526 
 527 #if ENABLE_ACL
 528         user = crm_element_value(command, "user");
 529         if (user) {
 530             client->user = strdup(user);
 531         }
 532 #endif
 533 
 534         /* send ACK */
 535         reg = create_xml_node(NULL, "cib_result");
 536         crm_xml_add(reg, F_CIB_OPERATION, CRM_OP_REGISTER);
 537         crm_xml_add(reg, F_CIB_CLIENTID, client->id);
 538         crm_remote_send(client->remote, reg);
 539         free_xml(reg);
 540         free_xml(command);
 541     }
 542 
 543     command = crm_remote_parse_buffer(client->remote);
 544     while (command) {
 545         crm_trace("command received");
 546         cib_handle_remote_msg(client, command);
 547         free_xml(command);
 548         command = crm_remote_parse_buffer(client->remote);
 549     }
 550 
 551     if (disconnected) {
 552         crm_trace("disconnected while receiving remote cib msg.");
 553         return -1;
 554     }
 555 
 556     return 0;
 557 }
 558 
 559 #ifdef HAVE_PAM
 560 /*
 561  * Useful Examples:
 562  *    http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html
 563  *    http://developer.apple.com/samplecode/CryptNoMore/index.html
 564  */
 565 static int
 566 construct_pam_passwd(int num_msg, const struct pam_message **msg,
     /* [previous][next][first][last][top][bottom][index][help] */
 567                      struct pam_response **response, void *data)
 568 {
 569     int count = 0;
 570     struct pam_response *reply;
 571     char *string = (char *)data;
 572 
 573     CRM_CHECK(data, return PAM_CONV_ERR);
 574     CRM_CHECK(num_msg == 1, return PAM_CONV_ERR);       /* We only want to handle one message */
 575 
 576     reply = calloc(1, sizeof(struct pam_response));
 577     CRM_ASSERT(reply != NULL);
 578 
 579     for (count = 0; count < num_msg; ++count) {
 580         switch (msg[count]->msg_style) {
 581             case PAM_TEXT_INFO:
 582                 crm_info("PAM: %s", msg[count]->msg);
 583                 break;
 584             case PAM_PROMPT_ECHO_OFF:
 585             case PAM_PROMPT_ECHO_ON:
 586                 reply[count].resp_retcode = 0;
 587                 reply[count].resp = string;     /* We already made a copy */
 588             case PAM_ERROR_MSG:
 589                 /* In theory we'd want to print this, but then
 590                  * we see the password prompt in the logs
 591                  */
 592                 /* crm_err("PAM error: %s", msg[count]->msg); */
 593                 break;
 594             default:
 595                 crm_err("Unhandled conversation type: %d", msg[count]->msg_style);
 596                 goto bail;
 597         }
 598     }
 599 
 600     *response = reply;
 601     reply = NULL;
 602 
 603     return PAM_SUCCESS;
 604 
 605   bail:
 606     for (count = 0; count < num_msg; ++count) {
 607         if (reply[count].resp != NULL) {
 608             switch (msg[count]->msg_style) {
 609                 case PAM_PROMPT_ECHO_ON:
 610                 case PAM_PROMPT_ECHO_OFF:
 611                     /* Erase the data - it contained a password */
 612                     while (*(reply[count].resp)) {
 613                         *(reply[count].resp)++ = '\0';
 614                     }
 615                     free(reply[count].resp);
 616                     break;
 617             }
 618             reply[count].resp = NULL;
 619         }
 620     }
 621     free(reply);
 622     reply = NULL;
 623 
 624     return PAM_CONV_ERR;
 625 }
 626 #endif
 627 
 628 int
 629 authenticate_user(const char *user, const char *passwd)
     /* [previous][next][first][last][top][bottom][index][help] */
 630 {
 631 #ifndef HAVE_PAM
 632     gboolean pass = TRUE;
 633 #else
 634     int rc = 0;
 635     gboolean pass = FALSE;
 636     const void *p_user = NULL;
 637 
 638     struct pam_conv p_conv;
 639     struct pam_handle *pam_h = NULL;
 640     static const char *pam_name = NULL;
 641 
 642     if (pam_name == NULL) {
 643         pam_name = getenv("CIB_pam_service");
 644     }
 645     if (pam_name == NULL) {
 646         pam_name = "login";
 647     }
 648 
 649     p_conv.conv = construct_pam_passwd;
 650     p_conv.appdata_ptr = strdup(passwd);
 651 
 652     rc = pam_start(pam_name, user, &p_conv, &pam_h);
 653     if (rc != PAM_SUCCESS) {
 654         crm_err("Could not initialize PAM: %s (%d)", pam_strerror(pam_h, rc), rc);
 655         goto bail;
 656     }
 657 
 658     rc = pam_authenticate(pam_h, 0);
 659     if (rc != PAM_SUCCESS) {
 660         crm_err("Authentication failed for %s: %s (%d)", user, pam_strerror(pam_h, rc), rc);
 661         goto bail;
 662     }
 663 
 664     /* Make sure we authenticated the user we wanted to authenticate.
 665      * Since we also run as non-root, it might be worth pre-checking
 666      * the user has the same EID as us, since that the only user we
 667      * can authenticate.
 668      */
 669     rc = pam_get_item(pam_h, PAM_USER, &p_user);
 670     if (rc != PAM_SUCCESS) {
 671         crm_err("Internal PAM error: %s (%d)", pam_strerror(pam_h, rc), rc);
 672         goto bail;
 673 
 674     } else if (p_user == NULL) {
 675         crm_err("Unknown user authenticated.");
 676         goto bail;
 677 
 678     } else if (safe_str_neq(p_user, user)) {
 679         crm_err("User mismatch: %s vs. %s.", (const char *)p_user, (const char *)user);
 680         goto bail;
 681     }
 682 
 683     rc = pam_acct_mgmt(pam_h, 0);
 684     if (rc != PAM_SUCCESS) {
 685         crm_err("Access denied: %s (%d)", pam_strerror(pam_h, rc), rc);
 686         goto bail;
 687     }
 688     pass = TRUE;
 689 
 690   bail:
 691     pam_end(pam_h, rc);
 692 #endif
 693     return pass;
 694 }

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