diff --git a/crm/cib/main.c b/crm/cib/main.c index 5a8cc2820d..e763e1a0f5 100644 --- a/crm/cib/main.c +++ b/crm/cib/main.c @@ -1,573 +1,574 @@ /* $Id: main.c,v 1.56 2006/07/18 06:14:18 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* #include */ #include /* #include */ #include #include #include #include #include #include #include #include #include #if HAVE_LIBXML2 # include #endif extern int init_remote_listener(int port); gboolean cib_shutdown_flag = FALSE; gboolean stand_alone = FALSE; gboolean per_action_cib = FALSE; enum cib_errors cib_status = cib_ok; extern char *ccm_transition_id; extern void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int ); GMainLoop* mainloop = NULL; const char* crm_system_name = CRM_SYSTEM_CIB; char *cib_our_uname = NULL; oc_ev_t *cib_ev_token; gboolean cib_writes_enabled = TRUE; void usage(const char* cmd, int exit_status); int cib_init(void); gboolean cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name); gboolean cib_shutdown(int nsig, gpointer unused); void cib_ha_connection_destroy(gpointer user_data); gboolean startCib(const char *filename); extern gboolean cib_msg_timeout(gpointer data); extern int write_cib_contents(gpointer p); GHashTable *client_list = NULL; GHashTable *ccm_membership = NULL; GHashTable *peer_hash = NULL; ll_cluster_t *hb_conn = NULL; GTRIGSource *cib_writer = NULL; char *channel1 = NULL; char *channel2 = NULL; char *channel3 = NULL; char *channel4 = NULL; char *channel5 = NULL; #define OPTARGS "hVsf" void cib_cleanup(void); static void cib_diskwrite_complete(gpointer userdata, int status, int signo, int exitcode) { if(exitcode != LSB_EXIT_OK || signo != 0 || status != 0) { crm_err("Disk write failed: status=%d, signo=%d, exitcode=%d", status, signo, exitcode); if(cib_writes_enabled) { crm_err("Disabling disk writes after write failure"); cib_writes_enabled = FALSE; } } else { crm_debug_2("Disk write passed"); } } int main(int argc, char ** argv) { int flag; int rc = 0; int argerr = 0; crm_log_init(crm_system_name); G_main_add_SignalHandler( G_PRIORITY_HIGH, SIGTERM, cib_shutdown, NULL, NULL); cib_writer = G_main_add_tempproc_trigger( G_PRIORITY_LOW, write_cib_contents, "write_cib_contents", NULL, NULL, NULL, cib_diskwrite_complete); EnableProcLogging(); set_sigchld_proctrack(G_PRIORITY_HIGH); client_list = g_hash_table_new(g_str_hash, g_str_equal); ccm_membership = g_hash_table_new_full( g_str_hash, g_str_equal, g_hash_destroy_str, NULL); peer_hash = g_hash_table_new_full( g_str_hash, g_str_equal,g_hash_destroy_str, g_hash_destroy_str); while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { switch(flag) { case 'V': alter_debug(DEBUG_INC); break; case 's': stand_alone = TRUE; cl_log_enable_stderr(1); break; case 'h': /* Help message */ usage(crm_system_name, LSB_EXIT_OK); break; case 'f': per_action_cib = TRUE; break; default: ++argerr; break; } } crm_info("Retrieval of a per-action CIB: %s", per_action_cib?"enabled":"disabled"); if (optind > argc) { ++argerr; } if (argerr) { usage(crm_system_name,LSB_EXIT_GENERIC); } /* read local config file */ rc = cib_init(); CRM_CHECK(g_hash_table_size(client_list) == 0, crm_err("Memory leak")); cib_cleanup(); if(hb_conn) { hb_conn->llc_ops->delete(hb_conn); } #ifdef HA_MALLOC_TRACK cl_malloc_dump_allocated(LOG_ERR, FALSE); #endif crm_info("Done"); return rc; } void cib_cleanup(void) { g_hash_table_destroy(ccm_membership); g_hash_table_destroy(client_list); g_hash_table_destroy(peer_hash); crm_free(ccm_transition_id); crm_free(cib_our_uname); #if HAVE_LIBXML2 xmlCleanupParser(); #endif crm_free(channel1); crm_free(channel2); crm_free(channel3); crm_free(channel4); crm_free(channel5); } unsigned long cib_num_ops = 0; const char *cib_stat_interval = "10min"; unsigned long cib_num_local = 0, cib_num_updates = 0, cib_num_fail = 0; unsigned long cib_bad_connects = 0, cib_num_timeouts = 0; longclock_t cib_call_time = 0; gboolean cib_stats(gpointer data); gboolean cib_stats(gpointer data) { int local_log_level = LOG_DEBUG; static unsigned long last_stat = 0; unsigned int cib_calls_ms = 0; static unsigned long cib_stat_interval_ms = 0; if(cib_stat_interval_ms == 0) { cib_stat_interval_ms = crm_get_msec(cib_stat_interval); } cib_calls_ms = longclockto_ms(cib_call_time); if((cib_num_ops - last_stat) > 0) { unsigned long calls_diff = cib_num_ops - last_stat; double stat_1 = (1000*cib_calls_ms)/calls_diff; local_log_level = LOG_INFO; do_crm_log(local_log_level, "Processed %lu operations" " (%.2fus average, %lu%% utilization) in the last %s", calls_diff, stat_1, (100*cib_calls_ms)/cib_stat_interval_ms, cib_stat_interval); } do_crm_log(local_log_level+1, "\tDetail: %lu operations (%ums total)" " (%lu local, %lu updates, %lu failures," " %lu timeouts, %lu bad connects)", cib_num_ops, cib_calls_ms, cib_num_local, cib_num_updates, cib_num_fail, cib_bad_connects, cib_num_timeouts); #ifdef HA_MALLOC_TRACK cl_malloc_dump_allocated(LOG_DEBUG, TRUE); #endif last_stat = cib_num_ops; cib_call_time = 0; return TRUE; } int cib_init(void) { gboolean was_error = FALSE; if(startCib("cib.xml") == FALSE){ crm_crit("Cannot start CIB... terminating"); exit(1); } if(stand_alone == FALSE) { hb_conn = ll_cluster_new("heartbeat"); if(cib_register_ha(hb_conn, CRM_SYSTEM_CIB) == FALSE) { crm_crit("Cannot sign in to heartbeat... terminating"); exit(1); } } else { cib_our_uname = crm_strdup("localhost"); - init_remote_listener(9899); - mainloop = g_main_new(FALSE); - g_main_run(mainloop); } channel1 = crm_strdup(cib_channel_callback); was_error = init_server_ipc_comms( channel1, cib_client_connect_null, default_ipc_connection_destroy); channel2 = crm_strdup(cib_channel_ro); was_error = was_error || init_server_ipc_comms( channel2, cib_client_connect_rw_ro, default_ipc_connection_destroy); channel3 = crm_strdup(cib_channel_rw); was_error = was_error || init_server_ipc_comms( channel3, cib_client_connect_rw_ro, default_ipc_connection_destroy); channel4 = crm_strdup(cib_channel_rw_synchronous); was_error = was_error || init_server_ipc_comms( channel4, cib_client_connect_rw_synch, default_ipc_connection_destroy); channel5 = crm_strdup(cib_channel_ro_synchronous); was_error = was_error || init_server_ipc_comms( channel5, cib_client_connect_ro_synch, default_ipc_connection_destroy); if(stand_alone) { if(was_error) { crm_err("Couldnt start"); return 1; } cib_is_master = TRUE; /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); crm_info("Starting %s mainloop", crm_system_name); /* Gmain_timeout_add(crm_get_msec("10s"), cib_msg_timeout, NULL); */ /* Gmain_timeout_add( */ /* crm_get_msec(cib_stat_interval), cib_stats, NULL); */ g_main_run(mainloop); return_to_orig_privs(); return 0; } if(was_error == FALSE) { crm_debug_3("Be informed of CRM Client Status changes"); if (HA_OK != hb_conn->llc_ops->set_cstatus_callback( hb_conn, cib_client_status_callback, hb_conn)) { crm_err("Cannot set cstatus callback: %s", hb_conn->llc_ops->errmsg(hb_conn)); was_error = TRUE; } else { crm_debug_3("Client Status callback set"); } } if(was_error == FALSE) { gboolean did_fail = TRUE; int num_ccm_fails = 0; int max_ccm_fails = 30; int ret; int cib_ev_fd; while(did_fail && was_error == FALSE) { did_fail = FALSE; crm_debug_3("Registering with CCM"); ret = oc_ev_register(&cib_ev_token); if (ret != 0) { crm_warn("CCM registration failed"); did_fail = TRUE; } if(did_fail == FALSE) { crm_debug_3("Setting up CCM callbacks"); ret = oc_ev_set_callback( cib_ev_token, OC_EV_MEMB_CLASS, cib_ccm_msg_callback, NULL); if (ret != 0) { crm_warn("CCM callback not set"); did_fail = TRUE; } } if(did_fail == FALSE) { oc_ev_special(cib_ev_token, OC_EV_MEMB_CLASS, 0); crm_debug_3("Activating CCM token"); ret = oc_ev_activate(cib_ev_token, &cib_ev_fd); if (ret != 0){ crm_warn("CCM Activation failed"); did_fail = TRUE; } } if(did_fail) { num_ccm_fails++; oc_ev_unregister(cib_ev_token); if(num_ccm_fails < max_ccm_fails){ crm_warn("CCM Connection failed" " %d times (%d max)", num_ccm_fails, max_ccm_fails); sleep(1); } else { crm_err("CCM Activation failed" " %d (max) times", num_ccm_fails); was_error = TRUE; } } } if(was_error == FALSE) { crm_debug_3("CCM Activation passed... all set to go!"); G_main_add_fd(G_PRIORITY_HIGH, cib_ev_fd, FALSE, cib_ccm_dispatch, cib_ev_token, default_ipc_connection_destroy); } } if(was_error == FALSE) { /* Async get client status information in the cluster */ crm_debug_3("Requesting an initial dump of CIB client_status"); hb_conn->llc_ops->client_status( hb_conn, NULL, CRM_SYSTEM_CIB, -1); /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); crm_info("Starting %s mainloop", crm_system_name); Gmain_timeout_add(crm_get_msec("10s"), cib_msg_timeout, NULL); Gmain_timeout_add( crm_get_msec(cib_stat_interval), cib_stats, NULL); g_main_run(mainloop); return_to_orig_privs(); } else { crm_err("Couldnt start all communication channels, exiting."); } return 0; } void usage(const char* cmd, int exit_status) { FILE* stream; stream = exit_status ? stderr : stdout; fprintf(stream, "usage: %s [-srkh]" "[-c configure file]\n", cmd); /* fprintf(stream, "\t-d\tsets debug level\n"); */ /* fprintf(stream, "\t-s\tgets daemon status\n"); */ /* fprintf(stream, "\t-r\trestarts daemon\n"); */ /* fprintf(stream, "\t-k\tstops daemon\n"); */ /* fprintf(stream, "\t-h\thelp message\n"); */ fflush(stream); exit(exit_status); } gboolean cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name) { const char *uname = NULL; crm_info("Signing in with Heartbeat"); if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) { crm_err("Cannot sign on with heartbeat: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } crm_debug_3("Be informed of CIB messages"); if (HA_OK != hb_cluster->llc_ops->set_msg_callback( hb_cluster, T_CIB, cib_peer_callback, hb_cluster)){ crm_err("Cannot set msg callback: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } crm_debug_3("Finding our node name"); if ((uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) { crm_err("get_mynodeid() failed"); return FALSE; } cib_our_uname = crm_strdup(uname); crm_info("FSA Hostname: %s", cib_our_uname); crm_debug_3("Adding channel to mainloop"); G_main_add_IPC_Channel( G_PRIORITY_DEFAULT, hb_cluster->llc_ops->ipcchan(hb_cluster), FALSE, cib_ha_dispatch, hb_cluster /* userdata */, cib_ha_connection_destroy); return TRUE; } void cib_ha_connection_destroy(gpointer user_data) { if(cib_shutdown_flag) { crm_info("Heartbeat disconnection complete... exiting"); } else { crm_err("Heartbeat connection lost! Exiting."); } uninitializeCib(); if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { exit(LSB_EXIT_OK); } } static void disconnect_cib_client(gpointer key, gpointer value, gpointer user_data) { cib_client_t *a_client = value; crm_debug_2("Processing client %s/%s... send=%d, recv=%d", a_client->name, a_client->channel_name, (int)a_client->channel->send_queue->current_qlen, (int)a_client->channel->recv_queue->current_qlen); if(a_client->channel->ch_status == IPC_CONNECT) { a_client->channel->ops->resume_io(a_client->channel); if(a_client->channel->send_queue->current_qlen != 0 || a_client->channel->recv_queue->current_qlen != 0) { crm_info("Flushed messages to/from %s/%s... send=%d, recv=%d", a_client->name, a_client->channel_name, (int)a_client->channel->send_queue->current_qlen, (int)a_client->channel->recv_queue->current_qlen); } } if(a_client->channel->ch_status == IPC_CONNECT) { crm_warn("Disconnecting %s/%s...", a_client->name, a_client->channel_name); a_client->channel->ops->disconnect(a_client->channel); } } extern gboolean cib_process_disconnect( IPC_Channel *channel, cib_client_t *cib_client); gboolean cib_shutdown(int nsig, gpointer unused) { if(cib_shutdown_flag == FALSE) { cib_shutdown_flag = TRUE; crm_debug("Disconnecting %d clients", g_hash_table_size(client_list)); g_hash_table_foreach(client_list, disconnect_cib_client, NULL); crm_info("Disconnected %d clients", g_hash_table_size(client_list)); cib_process_disconnect(NULL, NULL); } else { crm_info("Waiting for %d clients to disconnect...", g_hash_table_size(client_list)); } return TRUE; } gboolean startCib(const char *filename) { gboolean active = FALSE; crm_data_t *cib = readCibXmlFile(WORKING_DIR, filename, TRUE); CRM_ASSERT(cib != NULL); if(activateCibXml(cib, filename) == 0) { + int port = 0; active = TRUE; + ha_msg_value_int(cib, "remote_access_port", &port); + init_remote_listener(port); + crm_info("CIB Initialization completed successfully"); if(per_action_cib) { uninitializeCib(); } } return active; } diff --git a/crm/cib/remote.c b/crm/cib/remote.c index ba9b2476eb..d2f1427999 100644 --- a/crm/cib/remote.c +++ b/crm/cib/remote.c @@ -1,574 +1,579 @@ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" /* #undef HAVE_PAM_PAM_APPL_H */ /* #undef HAVE_GNUTLS_GNUTLS_H */ #ifdef HAVE_GNUTLS_GNUTLS_H # undef KEYFILE # include #endif #include #include #if HAVE_SECURITY_PAM_APPL_H # include # define HAVE_PAM 1 #else # if HAVE_PAM_PAM_APPL_H # include # define HAVE_PAM 1 # endif #endif int init_remote_listener(int port); char *cib_recv_remote_msg(void *session); void cib_send_remote_msg(void *session, HA_Message *msg); #ifdef HAVE_GNUTLS_GNUTLS_H # define DH_BITS 1024 const int tls_kx_order[] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, 0 }; gnutls_dh_params dh_params; gnutls_anon_server_credentials anon_cred; char *cib_send_tls(gnutls_session_t *session, HA_Message *msg); char *cib_recv_tls(gnutls_session_t *session); #endif extern int num_clients; int authenticate_user(const char* user, const char* passwd); gboolean cib_remote_listen(int ssock, gpointer data); gboolean cib_remote_msg(int csock, gpointer data); char *cib_send_plaintext(int sock, HA_Message *msg); char *cib_recv_plaintext(int sock); extern void cib_process_request( HA_Message *request, gboolean privileged, gboolean force_synchronous, gboolean from_peer, cib_client_t *cib_client); #ifdef HAVE_GNUTLS_GNUTLS_H static void debug_log(int level, const char *str) { fputs (str, stderr); } static gnutls_session * create_tls_session(int csock) { int rc = 0; gnutls_session *session; session = (gnutls_session*)gnutls_malloc(sizeof(gnutls_session)); gnutls_init(session, GNUTLS_SERVER); gnutls_set_default_priority(*session); gnutls_kx_set_priority (*session, tls_kx_order); gnutls_credentials_set(*session, GNUTLS_CRD_ANON, anon_cred); gnutls_transport_set_ptr(*session, (gnutls_transport_ptr) GINT_TO_POINTER(csock)); do { rc = gnutls_handshake (*session); } while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN); if (rc < 0) { crm_err("Handshake failed: %s", gnutls_strerror(rc)); gnutls_deinit(*session); gnutls_free(session); return NULL; } return session; } char* cib_send_tls(gnutls_session_t *session, HA_Message *msg) { char *xml_text = NULL; ha_msg_mod(msg, F_XML_TAGNAME, "cib_result"); crm_log_xml(LOG_DEBUG_2, "Result: ", msg); xml_text = dump_xml_unformatted(msg); if(xml_text != NULL) { int len = strlen(xml_text); len++; /* null char */ crm_debug_3("Message size: %d", len); gnutls_record_send (*session, xml_text, len); } crm_free(xml_text); return NULL; } char* cib_recv_tls(gnutls_session_t *session) { int len = 0; char* buf = NULL; int chunk_size = 512; if (session == NULL) { return NULL; } crm_malloc0(buf, chunk_size); while(1) { int rc = gnutls_record_recv(*session, buf+len, chunk_size); if (rc == 0) { if(len == 0) { goto bail; } return buf; } else if(rc > 0 && rc < chunk_size) { return buf; } else if(rc == chunk_size) { len += chunk_size; crm_realloc(buf, len); CRM_ASSERT(buf != NULL); } if(rc < 0 && rc != GNUTLS_E_INTERRUPTED && rc != GNUTLS_E_AGAIN) { cl_perror("Error receiving message: %d", rc); goto bail; } } bail: crm_free(buf); return NULL; } #endif int init_remote_listener(int port) { int ssock; struct sockaddr_in saddr; int optval; - if(port < 0) { + if(port <= 0) { /* dont start it */ return 0; } #ifdef HAVE_GNUTLS_GNUTLS_H + crm_notice("Starting a tls listener on port %d.", port); /* init pam & gnutls lib */ gnutls_global_init(); /* gnutls_global_set_log_level (10); */ gnutls_global_set_log_function (debug_log); gnutls_dh_params_init(&dh_params); gnutls_dh_params_generate2(dh_params, DH_BITS); gnutls_anon_allocate_server_credentials (&anon_cred); gnutls_anon_set_server_dh_params (anon_cred, dh_params); +#else + crm_notice("Starting a plaintext listener on port %d.", port); #endif /* create server socket */ ssock = socket(AF_INET, SOCK_STREAM, 0); if (ssock == -1) { crm_err("Can not create server socket. Shutting down."); return -1; } /* reuse address */ optval = 1; setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); /* bind server socket*/ memset(&saddr, '\0', sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(port); if (bind(ssock, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { crm_err("Can not bind server socket. Shutting down."); return -2; } if (listen(ssock, 10) == -1) { crm_err("Can not start listen. Shutting down."); return -3; } G_main_add_fd(G_PRIORITY_HIGH, ssock, FALSE, cib_remote_listen, NULL, default_ipc_connection_destroy); return 0; } static int check_group_membership(const char* usr, const char* grp) { int index = 0; struct group *group = NULL; CRM_CHECK(usr != NULL, return FALSE); CRM_CHECK(grp != NULL, return FALSE); group = getgrnam(grp); if (group == NULL) { crm_err("No group named '%s' exists!", grp); return FALSE; } while (TRUE) { char* member = group->gr_mem[index++]; if(member == NULL) { break; } else if (crm_str_eq(usr, member, TRUE)) { return TRUE; } }; return FALSE; } #define WELCOME "" gboolean cib_remote_listen(int ssock, gpointer data) { int lpc = 0; int csock; unsigned laddr; char *msg = NULL; struct sockaddr_in addr; #ifdef HAVE_GNUTLS_GNUTLS_H gnutls_session *session = NULL; #endif cib_client_t *new_client = NULL; crm_data_t *login = NULL; const char *user = NULL; const char *pass = NULL; const char *tmp = NULL; cl_uuid_t client_id; char uuid_str[UU_UNPARSE_SIZEOF]; crm_debug("New connection"); /* accept the connection */ laddr = sizeof(addr); csock = accept(ssock, (struct sockaddr*)&addr, &laddr); if (csock == -1) { crm_err("accept socket failed"); return TRUE; } #ifdef HAVE_GNUTLS_GNUTLS_H /* create gnutls session for the server socket */ session = create_tls_session(csock); if (session == NULL) { crm_err("TLS session creation failed"); close(csock); return TRUE; } #endif do { crm_debug_2("Iter: %d", lpc++); #ifdef HAVE_GNUTLS_GNUTLS_H msg = cib_recv_remote_msg(session); #else msg = cib_recv_remote_msg(GINT_TO_POINTER(csock)); #endif sleep(1); } while(msg == NULL && lpc < 10); /* convert to xml */ login = string2xml(msg); crm_log_xml_err(login, "Login: "); if(login == NULL) { goto bail; } tmp = crm_element_name(login); if(safe_str_neq(tmp, "cib_command")) { goto bail; } tmp = crm_element_value(login, "op"); if(safe_str_neq(tmp, "authenticate")) { goto bail; } user = crm_element_value(login, "user"); pass = crm_element_value(login, "password"); if(check_group_membership(user, "admin") == FALSE) { crm_err("User is not a member of the required group"); goto bail; } else if (authenticate_user(user, pass) == FALSE) { crm_err("PAM auth failed"); goto bail; } /* send ACK */ crm_err("Sending '%s' size=%d", WELCOME, (int)sizeof (WELCOME)); crm_malloc0(new_client, sizeof(cib_client_t)); num_clients++; new_client->channel_name = "remote"; cl_uuid_generate(&client_id); cl_uuid_unparse(&client_id, uuid_str); CRM_CHECK(new_client->id == NULL, crm_free(new_client->id)); new_client->id = crm_strdup(uuid_str); new_client->callback_id = NULL; #ifdef HAVE_GNUTLS_GNUTLS_H new_client->channel = (void*)session; gnutls_record_send (*session, WELCOME, sizeof (WELCOME)); #else new_client->channel = GINT_TO_POINTER(csock); write(csock, WELCOME, sizeof (WELCOME)); #endif new_client->source = (void*)G_main_add_fd( G_PRIORITY_HIGH, csock, FALSE, cib_remote_msg, new_client, default_ipc_connection_destroy); g_hash_table_insert(client_list, new_client->id, new_client); return TRUE; bail: #ifdef HAVE_GNUTLS_GNUTLS_H gnutls_bye(*session, GNUTLS_SHUT_RDWR); gnutls_deinit(*session); gnutls_free(session); #endif close(csock); return TRUE; } gboolean cib_remote_msg(int csock, gpointer data) { cl_uuid_t call_id; char call_uuid[UU_UNPARSE_SIZEOF]; const char *value = NULL; crm_data_t *command = NULL; cib_client_t *client = data; char* msg = cib_recv_remote_msg(client->channel); if(msg == NULL) { return FALSE; } command = string2xml(msg); if(command == NULL) { - crm_err("Could not parse: %s", msg); + crm_info("Could not parse command: %s", msg); goto bail; } crm_log_xml(LOG_MSG+1, "Command: ", command); value = crm_element_name(command); if(safe_str_neq(value, "cib_command")) { goto bail; } cl_uuid_generate(&call_id); cl_uuid_unparse(&call_id, call_uuid); crm_xml_add(command, F_TYPE, T_CIB); crm_xml_add(command, F_CIB_CLIENTID, client->id); crm_xml_add(command, F_CIB_CLIENTNAME, client->name); crm_xml_add(command, F_CIB_CALLID, call_uuid); if(crm_element_value(command, F_CIB_CALLOPTS) == NULL) { crm_xml_add_int(command, F_CIB_CALLOPTS, 0); } crm_log_xml(LOG_MSG, "Fixed Command: ", command); /* unset dangerous options */ xml_remove_prop(command, F_ORIG); xml_remove_prop(command, F_CIB_HOST); xml_remove_prop(command, F_CIB_GLOBAL_UPDATE); cib_process_request(command, TRUE, TRUE, FALSE, client); bail: free_xml(command); crm_free(msg); return TRUE; } #ifdef HAVE_PAM /* * Useful Examples: * http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html * http://developer.apple.com/samplecode/CryptNoMore/index.html */ static int construct_pam_passwd(int n, const struct pam_message **msg, struct pam_response **resp, void *data) { struct pam_response *reply; int i; char* passwd = (char*)data; crm_malloc0(reply, n * sizeof(*reply)); CRM_ASSERT(reply != NULL); /* Construct a PAM password message */ for (i = 0; i < n; ++i) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_OFF: case PAM_PROMPT_ECHO_ON: reply[i].resp = passwd; break; default: /* case PAM_ERROR_MSG: */ /* case PAM_TEXT_INFO: */ - crm_err("Unhandled message type: %d", msg[i]->msg_style); + crm_err("Unhandled message type: %d", + msg[i]->msg_style); goto bail; break; } } *resp = reply; return PAM_SUCCESS; bail: crm_free(reply); return PAM_CONV_ERR; } #endif int authenticate_user(const char* user, const char* passwd) { #ifndef HAVE_PAM gboolean pass = TRUE; #else gboolean pass = FALSE; int rc = 0; struct pam_handle *handle = NULL; struct pam_conv passwd_data; passwd_data.conv = construct_pam_passwd; passwd_data.appdata_ptr = strdup(passwd); rc = pam_start ("cib", user, &passwd_data, &handle); if (rc != PAM_SUCCESS) { goto bail; } rc = pam_authenticate (handle, 0); if(rc != PAM_SUCCESS) { - crm_err("pam_authenticate: %s (%d)", pam_strerror(handle, rc), rc); + crm_err("pam_authenticate: %s (%d)", + pam_strerror(handle, rc), rc); goto bail; } rc = pam_acct_mgmt(handle, 0); /* permitted access? */ if(rc != PAM_SUCCESS) { crm_err("pam_acct: %s (%d)", pam_strerror(handle, rc), rc); goto bail; } pass = TRUE; bail: rc = pam_end (handle, rc); #endif return pass; } char* cib_send_plaintext(int sock, HA_Message *msg) { char *xml_text = NULL; ha_msg_mod(msg, F_XML_TAGNAME, "cib_result"); crm_log_xml(LOG_DEBUG_2, "Result: ", msg); xml_text = dump_xml_unformatted(msg); if(xml_text != NULL) { int len = strlen(xml_text); len++; /* null char */ crm_debug_3("Message size: %d", len); write (sock, xml_text, len); } crm_free(xml_text); return NULL; } char* cib_recv_plaintext(int sock) { int len = 0; char* buf = NULL; int chunk_size = 512; crm_malloc0(buf, chunk_size); while(1) { int rc = recv(sock, buf+len, chunk_size, 0); if (rc == 0) { if(len == 0) { goto bail; } return buf; } else if(rc > 0 && rc < chunk_size) { return buf; } else if(rc == chunk_size) { len += chunk_size; crm_realloc(buf, len); CRM_ASSERT(buf != NULL); } if(rc < 0 && errno != EINTR) { cl_perror("Error receiving message: %d", rc); goto bail; } } bail: crm_free(buf); return NULL; } void cib_send_remote_msg(void *session, HA_Message *msg) { #ifdef HAVE_GNUTLS_GNUTLS_H cib_send_tls(session, msg); #else cib_send_plaintext(GPOINTER_TO_INT(session), msg); #endif } char * cib_recv_remote_msg(void *session) { #ifdef HAVE_GNUTLS_GNUTLS_H return cib_recv_tls(session); #else return cib_recv_plaintext(GPOINTER_TO_INT(session)); #endif } diff --git a/crm/crm-1.0.dtd b/crm/crm-1.0.dtd index f3b7685cd5..bf3b7d92ba 100644 --- a/crm/crm-1.0.dtd +++ b/crm/crm-1.0.dtd @@ -1,839 +1,840 @@