Page MenuHomeClusterLabs Projects

No OneTemporary

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

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)

Event Timeline