Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F4623570
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/cib/remote.c b/crm/cib/remote.c
index d2f1427999..efe42f6429 100644
--- a/crm/cib/remote.c
+++ b/crm/cib/remote.c
@@ -1,579 +1,581 @@
#include <crm/crm.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <libnet.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#include <crm/common/ipc.h>
#include <crm/common/xml.h>
#include "callbacks.h"
/* #undef HAVE_PAM_PAM_APPL_H */
/* #undef HAVE_GNUTLS_GNUTLS_H */
#ifdef HAVE_GNUTLS_GNUTLS_H
# undef KEYFILE
# include <gnutls/gnutls.h>
#endif
#include <pwd.h>
#include <grp.h>
#if HAVE_SECURITY_PAM_APPL_H
# include <security/pam_appl.h>
# define HAVE_PAM 1
#else
# if HAVE_PAM_PAM_APPL_H
# include <pam/pam_appl.h>
# 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) {
/* 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);
+ crm_warn("Starting a _plain_text_ listener on port %d.", port);
+#endif
+#ifndef HAVE_PAM
+ crm_warn("PAM is _not_ enabled!");
#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 "<cib_result cib_op=\"welecome\"/>"
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) {
+ if(check_group_membership(user, HA_APIGROUP) == 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_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);
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);
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
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 8, 4:10 PM (1 d, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2002251
Default Alt Text
(13 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment