0004a70072
Fix a few places where descriptors could leak in the client code. Signed-off-by: Ryan McCabe <rmccabe@redhat.com>
174 lines
4.2 KiB
C
174 lines
4.2 KiB
C
/*
|
|
Copyright Red Hat, Inc. 2006-2012
|
|
|
|
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, or (at your option) any
|
|
later version.
|
|
|
|
This program 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 program; see the file COPYING. If not, write to the
|
|
Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
|
|
MA 02139, USA.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <errno.h>
|
|
#include <nss.h>
|
|
|
|
/* Local includes */
|
|
#include "xvm.h"
|
|
#include "ip_lookup.h"
|
|
#include "simple_auth.h"
|
|
#include "options.h"
|
|
#include "tcp.h"
|
|
#include "mcast.h"
|
|
#include "debug.h"
|
|
#include "fdops.h"
|
|
|
|
void do_read_hostlist(int fd, int timeout);
|
|
|
|
static int
|
|
tcp_exchange(int fd, fence_auth_type_t auth, void *key,
|
|
size_t key_len, int timeout)
|
|
{
|
|
fd_set rfds;
|
|
struct timeval tv;
|
|
char ret = 1;
|
|
|
|
/* Ok, we're connected */
|
|
dbg_printf(3, "Issuing TCP challenge\n");
|
|
if (tcp_challenge(fd, auth, key, key_len, timeout) <= 0) {
|
|
/* Challenge failed */
|
|
printf("Invalid response to challenge\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Now they'll send us one, so we need to respond here */
|
|
dbg_printf(3, "Responding to TCP challenge\n");
|
|
if (tcp_response(fd, auth, key, key_len, timeout) <= 0) {
|
|
printf("Invalid response to challenge\n");
|
|
return 1;
|
|
}
|
|
|
|
dbg_printf(2, "TCP Exchange + Authentication done... \n");
|
|
|
|
FD_ZERO(&rfds);
|
|
FD_SET(fd, &rfds);
|
|
tv.tv_sec = timeout;
|
|
tv.tv_usec = 0;
|
|
|
|
ret = 1;
|
|
dbg_printf(3, "Waiting for return value from fence_virtd host\n");
|
|
if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
|
|
return -1;
|
|
|
|
/* Read return code */
|
|
if (_read_retry(fd, &ret, 1, &tv) < 0)
|
|
ret = 1;
|
|
|
|
if (ret == (char)RESP_HOSTLIST) /* hostlist */ {
|
|
do_read_hostlist(fd, timeout);
|
|
ret = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
tcp_fence_virt(fence_virt_args_t *args)
|
|
{
|
|
char key[MAX_KEY_LEN];
|
|
struct timeval tv;
|
|
int key_len = 0, fd = -1;
|
|
int ret;
|
|
struct in_addr ina;
|
|
struct in6_addr in6a;
|
|
fence_req_t freq;
|
|
|
|
/* Initialize NSS; required to do hashing, as silly as that
|
|
sounds... */
|
|
if (NSS_NoDB_Init(NULL) != SECSuccess) {
|
|
printf("Could not initialize NSS\n");
|
|
return 1;
|
|
}
|
|
|
|
if (args->net.auth != AUTH_NONE || args->net.hash != HASH_NONE) {
|
|
key_len = read_key_file(args->net.key_file, key, sizeof(key));
|
|
if (key_len < 0) {
|
|
printf("Could not read %s; trying without "
|
|
"authentication\n", args->net.key_file);
|
|
args->net.auth = AUTH_NONE;
|
|
args->net.hash = HASH_NONE;
|
|
key_len = 0;
|
|
}
|
|
}
|
|
|
|
/* Same wire protocol as fence_xvm */
|
|
memset(&freq, 0, sizeof(freq));
|
|
if (args->domain && strlen((char *)args->domain))
|
|
strncpy((char *)freq.domain, args->domain, sizeof(freq.domain));
|
|
freq.request = args->op;
|
|
freq.hashtype = args->net.hash;
|
|
freq.flags = 0;
|
|
if (args->flags & F_USE_UUID)
|
|
freq.flags |= RF_UUID;
|
|
gettimeofday(&tv, NULL);
|
|
freq.seqno = (uint32_t) tv.tv_usec;
|
|
sign_request(&freq, key, key_len);
|
|
|
|
/* XXX fixme */
|
|
if (inet_pton(PF_INET, args->net.ipaddr, &ina)) {
|
|
fd = ipv4_connect(&ina, args->net.port, 3);
|
|
} else if (inet_pton(PF_INET6, args->net.ipaddr, &in6a)) {
|
|
fd = ipv6_connect(&in6a, args->net.port, 3);
|
|
}
|
|
|
|
if (fd < 0) {
|
|
printf("Unable to connect to fence_virtd host %s:%d %s\n",
|
|
args->net.ipaddr, args->net.port, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
ret = _write_retry(fd, &freq, sizeof(freq), NULL);
|
|
if (ret != sizeof(freq)) {
|
|
perror("write");
|
|
close(fd);
|
|
return 1;
|
|
}
|
|
|
|
switch (args->net.auth) {
|
|
case AUTH_NONE:
|
|
case AUTH_SHA1:
|
|
case AUTH_SHA256:
|
|
case AUTH_SHA512:
|
|
ret = tcp_exchange(fd, args->net.auth, key, key_len,
|
|
args->timeout);
|
|
close(fd);
|
|
return ret;
|
|
break;
|
|
/* case AUTH_X509:
|
|
return ssl_exchange(...); */
|
|
default:
|
|
dbg_printf(3, "Unknown auth type: %d\n", args->net.auth);
|
|
close(fd);
|
|
return 1;
|
|
}
|
|
|
|
close(fd);
|
|
return 1;
|
|
}
|