diff options
author | Prasanna Kumar Kalever <prasanna.kalever@redhat.com> | 2017-01-15 13:59:04 +0530 |
---|---|---|
committer | Prasanna Kumar Kalever <prasanna.kalever@redhat.com> | 2017-01-16 17:39:28 +0530 |
commit | c5bcaaaf25e781c21d29dfb0f39b0aeb7edb8283 (patch) | |
tree | 3754ef31816e856b34007170afba07778df0cf76 | |
parent | 0a1c338a4814f91cd49b7747442d413c6b8f0dfa (diff) |
gluster-blockd: daemonize the utility
this patch,
deprecate ssh way of communicating between server nodes/pods
Reason: ssh way is hard to be accepted in container world (Kube).
An another option kubeExec way seems to be a bit weird,
to have uniform way of communication in container and
non container worlds, we prefer RPC.
From now we communicate via RPC, using a static port 24009
Hence, we have two components,
server component -> gluster-blockd (daemon)
client component -> gluster-block (cli)
Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 28 | ||||
-rw-r--r-- | gluster-block.c | 126 | ||||
-rw-r--r-- | gluster-blockd.c | 34 | ||||
-rw-r--r-- | rpc/block.h | 53 | ||||
-rw-r--r-- | rpc/block.x | 12 | ||||
-rw-r--r-- | rpc/block_clnt.c | 25 | ||||
-rw-r--r-- | rpc/block_svc.c | 102 | ||||
-rw-r--r-- | rpc/block_xdr.c | 16 | ||||
-rw-r--r-- | ssh-common.c | 388 | ||||
-rw-r--r-- | ssh-common.h | 22 | ||||
-rw-r--r-- | utils.c | 3 |
12 files changed, 328 insertions, 482 deletions
@@ -1,4 +1,5 @@ gluster-block +gluster-blockd *.o cscope.* tags @@ -12,11 +12,14 @@ CC = gcc -BIN = gluster-block -OBJS = glfs-operations.o ssh-common.o utils.o gluster-block.o +CLIENT = gluster-block +CDEP = glfs-operations.o utils.o rpc/block_clnt.c rpc/block_xdr.c gluster-block.o -CFLAGS = -g -Wall -LIBS := $(shell pkg-config --libs uuid glusterfs-api libssh) +SERVER = gluster-blockd +SDEP = rpc/block_svc.o rpc/block_xdr.o gluster-blockd.o utils.o + +CFLAGS = -g -ggdb -Wall +LIBS := $(shell pkg-config --libs uuid glusterfs-api) DEPS_LIST = gcc tcmu-runner targetcli @@ -25,12 +28,15 @@ MKDIR_P = mkdir -p LOGDIR = /var/log/ -all: $(BIN) +all: $(CLIENT) $(SERVER) -$(BIN): $(OBJS) +$(CLIENT): $(CDEP) @$(MKDIR_P) $(LOGDIR)$@ $(CC) $(CFLAGS) $(LIBS) $^ -o $@ +$(SERVER): $(SDEP) + $(CC) $(CFLAGS) $^ -o $@ + glfs-operations.o: glfs-operations.c glfs-operations.h $(foreach x, $(DEPS_LIST),\ $(if $(shell which $x), \ @@ -39,15 +45,15 @@ glfs-operations.o: glfs-operations.c glfs-operations.h $(error "No $x in PATH, install '$x' and continue ...")))) $(CC) $(CFLAGS) -c $< -o $@ -$(BIN).o: $(BIN).c +$(CLIENT).o: $(CLIENT).c $(CC) $(CFLAGS) -c $< -o $@ -install: $(BIN) - cp $< $(PREFIX)/ +install: $(CLIENT) $(SERVER) + cp $^ $(PREFIX)/ .PHONY: clean distclean clean distclean: - rm -f ./*.o $(BIN) + rm -f ./*.o ./rpc/*.o $(CLIENT) $(SERVER) uninstall: - rm -f $(PREFIX)/$(BIN) + rm -f $(PREFIX)/$(CLIENT) $(PREFIX)/$(SERVER) diff --git a/gluster-block.c b/gluster-block.c index 63d5be4..9a2564e 100644 --- a/gluster-block.c +++ b/gluster-block.c @@ -16,8 +16,9 @@ # include <uuid/uuid.h> # include "utils.h" +#include "rpc/block.h" # include "glfs-operations.h" -# include "ssh-common.h" + # define UUID_BUF_SIZE 50 # define CFG_STRING_SIZE 256 @@ -52,6 +53,26 @@ typedef blockServerDef *blockServerDefPtr; static void +gluster_block_1(char *host, char *cmd, blockTrans **reply) +{ + CLIENT *clnt; + + clnt = clnt_create (host, GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, "tcp"); + if (clnt == NULL) { + clnt_pcreateerror (host); + exit (1); + } + + *reply = block_exec_1(&cmd, clnt); + if (*reply == NULL) { + clnt_perror (clnt, "call failed"); + } + + clnt_destroy (clnt); +} + + +static void glusterBlockHelp(void) { MSG("%s", @@ -235,7 +256,7 @@ glusterBlockCreate(int count, char **options, char *name) blockServerDefPtr list; uuid_t out; glusterBlockDefPtr blk; - char *sshout; + blockTrans *reply; size_t i; if (GB_ALLOC(blk) < 0) @@ -345,55 +366,60 @@ glusterBlockCreate(int count, char **options, char *name) /* Created user-backed storage object LUN size 2147483648. */ for (i = 0; i < list->nhosts; i++) { MSG("[OnHost: %s]", list->hosts[i]); - sshout = glusterBlockSSHRun(list->hosts[i], cmd, true); - if (!sshout) { + gluster_block_1(list->hosts[i], cmd, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_CREATING_BACKEND, list->hosts[i]); ret = -1; goto out; } + MSG("%s", reply->out); asprintf(&iqn, "%s%s", IQN_PREFIX, blk->filename); asprintf(&exec, "%s %s %s", TARGETCLI_ISCSI, CREATE, iqn); - sshout = glusterBlockSSHRun(list->hosts[i], exec, true); - if (!sshout) { + gluster_block_1(list->hosts[i], exec, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_CREATING_IQN, list->hosts[i]); ret = -1; goto out; } + MSG("%s", reply->out); GB_FREE(exec); asprintf(&exec, "%s/%s/tpg1/luns %s %s/%s", TARGETCLI_ISCSI, iqn, CREATE, GLFS_PATH, name); - sshout = glusterBlockSSHRun(list->hosts[i], exec, true); - if (!sshout) { + gluster_block_1(list->hosts[i], exec, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_CREATING_LUN, list->hosts[i]); ret = -1; goto out; } + MSG("%s", reply->out); GB_FREE(exec); asprintf(&exec, "%s/%s/tpg1 set attribute %s", TARGETCLI_ISCSI, iqn, ATTRIBUTES); - sshout = glusterBlockSSHRun(list->hosts[i], exec, true); - if (!sshout) { + gluster_block_1(list->hosts[i], exec, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_SETTING_ATTRIBUTES, list->hosts[i]); ret = -1; goto out; } + MSG("%s", reply->out); GB_FREE(exec); GB_FREE(iqn); - sshout = glusterBlockSSHRun(list->hosts[i], TARGETCLI_SAVE, true); - if (!sshout) { + gluster_block_1(list->hosts[i], TARGETCLI_SAVE, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_SAVEING_CONFIG, list->hosts[i]); ret = -1; goto out; } + MSG("%s", reply->out); putchar('\n'); } @@ -498,37 +524,26 @@ glusterBlockParseCfgStringToDef(char* cfgstring, static char * getCfgstring(char* name, char *blkServer) { - FILE *fd; char *cmd; char *exec; - char *sshout; - char *buf = CALLOC(CFG_STRING_SIZE); + char *buf = NULL; + blockTrans *reply; asprintf(&cmd, "%s %s", TARGETCLI_GLFS, BACKEND_CFGSTR); asprintf(&exec, cmd, name); - sshout = glusterBlockSSHRun(blkServer, exec, false); - if (!sshout) { + gluster_block_1(blkServer, exec, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_GATHERING_CFGSTR, blkServer); - GB_FREE(buf); - buf = NULL; - goto fail; } - fd = fopen(sshout, "r"); - if (!fgets(buf, CFG_STRING_SIZE, fd)) { - GB_FREE(buf); - buf = NULL; - } - - fail: - fclose(fd); - remove(sshout); - GB_FREE(sshout); GB_FREE(cmd); GB_FREE(exec); + if(reply->out) + buf = strdup(reply->out); + return buf; } @@ -541,11 +556,10 @@ glusterBlockList(blockServerDefPtr blkServers) int ret; char *cmd; char *pos; - char *sshout; + char *size; char *cfgstring = NULL; - char buf[CFG_STRING_SIZE]; - FILE *fd = NULL; glusterBlockDefPtr blk = NULL; + blockTrans *reply; MSG("%s", "BlockName Volname Host Size Status"); @@ -553,17 +567,16 @@ glusterBlockList(blockServerDefPtr blkServers) for (i = 0; i < blkServers->nhosts; i++) { MSG("[OnHost: %s]", blkServers->hosts[i]); - sshout = glusterBlockSSHRun(blkServers->hosts[i], cmd, false); - if (!sshout) { + gluster_block_1(blkServers->hosts[i], cmd, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_LIST_BACKEND, blkServers->hosts[i]); ret = -1; goto fail; } - fd = fopen(sshout, "r"); - while (fgets(buf, sizeof(buf), fd)) { - pos = strtok(buf, "\n"); + pos = strtok (reply->out, "\n"); + while (pos != NULL) { cfgstring = getCfgstring(pos, blkServers->hosts[i]); if (!cfgstring) { @@ -583,30 +596,26 @@ glusterBlockList(blockServerDefPtr blkServers) fprintf(stdout, " %s %s %s %s %s\n", pos, blk->volume, blk->host, - glusterBlockListGetHumanReadableSize(blk->size), + size = glusterBlockListGetHumanReadableSize(blk->size), blk->status ? "Online" : "Offline"); GB_FREE(cfgstring); glusterBlockDefFree(blk); + pos = strtok (NULL, "\n"); } putchar('\n'); - fclose(fd); - remove(sshout); - GB_FREE(sshout); + GB_FREE(size); } GB_FREE(cmd); return 0; fail: - fclose(fd); - remove(sshout); glusterBlockDefFree(blk); GB_FREE(cfgstring); - GB_FREE(sshout); GB_FREE(cmd); return -1; @@ -620,10 +629,10 @@ glusterBlockDelete(char* name, blockServerDefPtr blkServers) int ret; char *cmd; char *exec = NULL; - char *sshout; char *cfgstring = NULL; char *iqn = NULL; glusterBlockDefPtr blk = NULL; + blockTrans *reply; asprintf(&cmd, "%s %s %s", TARGETCLI_GLFS, DELETE, name); @@ -638,14 +647,14 @@ glusterBlockDelete(char* name, blockServerDefPtr blkServers) goto fail; } - sshout = glusterBlockSSHRun(blkServers->hosts[i], cmd, true); - if (!sshout) { + gluster_block_1(blkServers->hosts[i], cmd, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_DELETING_BACKEND, blkServers->hosts[i]); ret = -1; goto fail; } - + MSG("%s", reply->out); /* cfgstring is constant across all tcmu nodes */ if (!blk) { if (GB_ALLOC(blk) < 0) @@ -660,24 +669,25 @@ glusterBlockDelete(char* name, blockServerDefPtr blkServers) asprintf(&iqn, "%s%s", IQN_PREFIX, blk->filename); asprintf(&exec, "%s %s %s", TARGETCLI_ISCSI, DELETE, iqn); - sshout = glusterBlockSSHRun(blkServers->hosts[i], exec, true); - if (!sshout) { + gluster_block_1(blkServers->hosts[i], exec, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_DELETING_IQN, blkServers->hosts[i]); ret = -1; goto fail; } + MSG("%s", reply->out); GB_FREE(exec); GB_FREE(iqn); - sshout = glusterBlockSSHRun(blkServers->hosts[i], TARGETCLI_SAVE, true); - if (!sshout) { + gluster_block_1(blkServers->hosts[i], TARGETCLI_SAVE, &reply); + if (!reply || reply->exit) { ERROR("%s on host: %s", FAILED_SAVEING_CONFIG, blkServers->hosts[i]); ret = -1; goto fail; } - + MSG("%s", reply->out); putchar('\n'); } @@ -690,7 +700,6 @@ glusterBlockDelete(char* name, blockServerDefPtr blkServers) fail: glusterBlockDefFree(blk); GB_FREE(cfgstring); - GB_FREE(iqn); GB_FREE(exec); GB_FREE(cmd); @@ -704,19 +713,20 @@ glusterBlockInfo(char* name, blockServerDefPtr blkServers) size_t i; int ret = 0; char *cmd; - char *sshout; + blockTrans *reply; asprintf(&cmd, "%s/%s %s", TARGETCLI_GLFS, name, INFO); for (i = 0; i < blkServers->nhosts; i++) { MSG("[OnHost: %s]", blkServers->hosts[i]); - sshout = glusterBlockSSHRun(blkServers->hosts[i], cmd, true); - if (!sshout) { + gluster_block_1(blkServers->hosts[i], cmd, &reply); + if (!reply || reply->exit) { ret = -1; ERROR("%s on host: %s", FAILED_GATHERING_INFO, blkServers->hosts[i]); goto fail; } + MSG("%s", reply->out); putchar('\n'); } diff --git a/gluster-blockd.c b/gluster-blockd.c new file mode 100644 index 0000000..18506ac --- /dev/null +++ b/gluster-blockd.c @@ -0,0 +1,34 @@ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include <stdio.h> + +#include "rpc/block.h" +#include "utils.h" + + +blockTrans * +block_exec_1_svc(char **cmd, struct svc_req *rqstp) +{ + FILE *fp; + static blockTrans *obj; + + if(GB_ALLOC(obj) < 0) + return NULL; + + if (GB_ALLOC_N(obj->out, 4096) < 0) { + GB_FREE(obj); + return NULL; + } + + fp = popen(*cmd, "r"); + if (fp != NULL) { + size_t newLen = fread(obj->out, sizeof(char), 4996, fp); + if (ferror( fp ) != 0) { + ERROR("%s", "Error reading command output\n"); + } else { + obj->out[newLen++] = '\0'; + } + obj->exit = WEXITSTATUS(pclose(fp)); + } + + return obj; +} diff --git a/rpc/block.h b/rpc/block.h new file mode 100644 index 0000000..54315b7 --- /dev/null +++ b/rpc/block.h @@ -0,0 +1,53 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _BLOCK_H_RPCGEN +#define _BLOCK_H_RPCGEN + +#include <rpc/rpc.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct blockTrans { + int exit; + char *out; +}; +typedef struct blockTrans blockTrans; + +#define GLUSTER_BLOCK 21215311 +#define GLUSTER_BLOCK_VERS 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define BLOCK_EXEC 1 +extern blockTrans * block_exec_1(char **, CLIENT *); +extern blockTrans * block_exec_1_svc(char **, struct svc_req *); +extern int gluster_block_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define BLOCK_EXEC 1 +extern blockTrans * block_exec_1(); +extern blockTrans * block_exec_1_svc(); +extern int gluster_block_1_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_blockTrans (XDR *, blockTrans*); + +#else /* K&R C */ +extern bool_t xdr_blockTrans (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_BLOCK_H_RPCGEN */ diff --git a/rpc/block.x b/rpc/block.x new file mode 100644 index 0000000..c88fdf2 --- /dev/null +++ b/rpc/block.x @@ -0,0 +1,12 @@ + + +struct blockTrans { + int exit; /* exit code of the command */ + string out<>; /* stdout of the command */ +}; + +program GLUSTER_BLOCK { + version GLUSTER_BLOCK_VERS { + blockTrans BLOCK_EXEC(string) = 1; + } = 1; +} = 21215311; /* B2 L12 O15 C3 K11 */ diff --git a/rpc/block_clnt.c b/rpc/block_clnt.c new file mode 100644 index 0000000..9e5b585 --- /dev/null +++ b/rpc/block_clnt.c @@ -0,0 +1,25 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include <memory.h> /* for memset */ +#include "block.h" + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +blockTrans * +block_exec_1(char **argp, CLIENT *clnt) +{ + static blockTrans clnt_res; + + memset((char *)&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call (clnt, BLOCK_EXEC, + (xdrproc_t) xdr_wrapstring, (caddr_t) argp, + (xdrproc_t) xdr_blockTrans, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} diff --git a/rpc/block_svc.c b/rpc/block_svc.c new file mode 100644 index 0000000..144b7e1 --- /dev/null +++ b/rpc/block_svc.c @@ -0,0 +1,102 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "block.h" +#include <stdio.h> +#include <stdlib.h> +#include <rpc/pmap_clnt.h> +#include <string.h> +#include <memory.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +static void +gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + char *block_exec_1_arg; + } argument; + char *result; + xdrproc_t _xdr_argument, _xdr_result; + char *(*local)(char *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case BLOCK_EXEC: + _xdr_argument = (xdrproc_t) xdr_wrapstring; + _xdr_result = (xdrproc_t) xdr_blockTrans; + local = (char *(*)(char *, struct svc_req *)) block_exec_1_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + result = (*local)((char *)&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + return; +} + +int +main (int argc, char **argv) +{ + register SVCXPRT *transp; + struct sockaddr_in addr; + int sockfd; + + pmap_unset (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS); + + if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + fprintf (stderr, "%s", "socket failed"); + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(24009); + + if (bind(sockfd, (struct sockaddr *)&addr, sizeof (addr)) < 0) { + fprintf (stderr, "%s", "bind failed"); + } + + if (listen(sockfd, 10) < 0) { + fprintf (stderr, "%s", "server: listen failed"); + exit(1); + } + + transp = svctcp_create(sockfd, 0, 0); + if (transp == NULL) { + fprintf (stderr, "%s", "cannot create tcp service"); + exit(1); + } + + if (!svc_register(transp, GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, gluster_block_1, IPPROTO_TCP)) { + fprintf (stderr, "%s", "unable to register (BLOCK_PROG, GLUSTER_BLOCK_VERS, tcp)."); + exit(1); + } + + svc_run (); + + fprintf (stderr, "%s", "svc_run returned"); + exit (1); + /* NOTREACHED */ +} diff --git a/rpc/block_xdr.c b/rpc/block_xdr.c new file mode 100644 index 0000000..cd8400e --- /dev/null +++ b/rpc/block_xdr.c @@ -0,0 +1,16 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "block.h" + +bool_t +xdr_blockTrans (XDR *xdrs, blockTrans *objp) +{ + if (!xdr_int (xdrs, &objp->exit)) + return FALSE; + if (!xdr_string (xdrs, &objp->out, ~0)) + return FALSE; + return TRUE; +} diff --git a/ssh-common.c b/ssh-common.c deleted file mode 100644 index bfa48b5..0000000 --- a/ssh-common.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# define _GNU_SOURCE - -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -# include <stdbool.h> -# include <errno.h> -# include <uuid/uuid.h> - -# include "utils.h" -# include "ssh-common.h" - - - -static int -glusterBlockSSHAuthKbdint(ssh_session blksession, const char *password) -{ - int err; - const char *ret; - const char *answer; - char buffer[128]; - size_t i; - int n; - - err = ssh_userauth_kbdint(blksession, NULL, NULL); - while (err == SSH_AUTH_INFO) { - ret = ssh_userauth_kbdint_getname(blksession); - if (ret && strlen(ret) > 0) - MSG("%s", ret); - - ret = ssh_userauth_kbdint_getinstruction(blksession); - if (ret && strlen(ret) > 0) - MSG("%s", ret); - - n = ssh_userauth_kbdint_getnprompts(blksession); - for (i = 0; i < n; i++) { - char echo; - - ret = ssh_userauth_kbdint_getprompt(blksession, i, &echo); - if (!ret) - break; - - if (echo) { - char *p; - - MSG("%s", ret); - - if (!fgets(buffer, sizeof(buffer), stdin)) - return SSH_AUTH_ERROR; - - buffer[sizeof(buffer) - 1] = '\0'; - if ((p = strchr(buffer, '\n'))) - *p = '\0'; - - if (ssh_userauth_kbdint_setanswer(blksession, i, buffer) < 0) - return SSH_AUTH_ERROR; - - memset(buffer, 0, strlen(buffer)); - } else { - if (password && strstr(ret, "Password:")) { - answer = password; - } else { - buffer[0] = '\0'; - - if (ssh_getpass(ret, buffer, sizeof(buffer), 0, 0) < 0) - return SSH_AUTH_ERROR; - - answer = buffer; - } - err = ssh_userauth_kbdint_setanswer(blksession, i, answer); - memset(buffer, 0, sizeof(buffer)); - if (err < 0) - return SSH_AUTH_ERROR; - } - } - err = ssh_userauth_kbdint(blksession, NULL, NULL); - } - - return err; -} - - -static int -glusterBlockSSHAuthConsole(ssh_session blksession) -{ - int rc; - int method; - char *banner; - char password[128] = {0}; - - // Try to authenticate - rc = ssh_userauth_none(blksession, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } - - method = ssh_userauth_list(blksession, NULL); - - while (rc != SSH_AUTH_SUCCESS) { - - // Try to authenticate through the "gssapi-with-mic" method. - if (method & SSH_AUTH_METHOD_GSSAPI_MIC) { - rc = ssh_userauth_gssapi(blksession); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - // Try to authenticate with public key first - if (method & SSH_AUTH_METHOD_PUBLICKEY) { - rc = ssh_userauth_publickey_auto(blksession, NULL, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - // Try to authenticate with keyboard interactive"; - if (method & SSH_AUTH_METHOD_INTERACTIVE) { - rc = glusterBlockSSHAuthKbdint(blksession, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - if (ssh_getpass("Password: ", password, sizeof(password), - 0, 0) < 0) - return SSH_AUTH_ERROR; - - // Try to authenticate with password - if (method & SSH_AUTH_METHOD_PASSWORD) { - rc = ssh_userauth_password(blksession, NULL, password); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - memset(password, 0, sizeof(password)); - } - - banner = ssh_get_issue_banner(blksession); - if (banner) { - ERROR("%s", banner); - ssh_string_free_char(banner); - } - - return rc; -} - - -static int -glusterBlockSSHVerifyKnownHost(ssh_session blksession) -{ - ssh_key srv_pubkey; - unsigned char *hash = NULL; - char *hexa; - char buf[10]; - size_t hlen; - int rc; - int ret; - - rc = ssh_get_publickey(blksession, &srv_pubkey); - if (rc < 0) - return -1; - - rc = ssh_get_publickey_hash(srv_pubkey, - SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen); - ssh_key_free(srv_pubkey); - if (rc < 0) - return -1; - - switch (ssh_is_server_known(blksession)) { - - case SSH_SERVER_KNOWN_OK: - break; /* ok we have password less access */ - - case SSH_SERVER_KNOWN_CHANGED: - ERROR("%s", "Host key for server changed : server's one is new :"); - ssh_print_hexa("Public key hash", hash, hlen); - ssh_clean_pubkey_hash(&hash); - ERROR("%s", "For security reason, connection will be stopped"); - return -1; - - case SSH_SERVER_FOUND_OTHER: - ERROR("%s", "The host key for this server was not found, but an other " - "type of key exists."); - ERROR("%s", "An attacker might change the default server key to " - "confuse your client into thinking the key does not exist" - "\nWe advise you to rerun the client with -d or -r for " - "more safety."); - return -1; - - case SSH_SERVER_FILE_NOT_FOUND: - ERROR("%s", "Could not find known host file. If you accept the host " - "key here, the file will be automatically created."); - /* fallback to SSH_SERVER_NOT_KNOWN behavior */ - - case SSH_SERVER_NOT_KNOWN: - hexa = ssh_get_hexa(hash, hlen); - ERROR("The server is unknown. Do you trust the host key ?\n" - "Public key hash: %s", hexa); - ssh_string_free_char(hexa); - if (!fgets(buf, sizeof(buf), stdin)) { - ret = -1; - goto fail; - } - if (strncasecmp(buf, "yes", 3) != 0) { - ret = -1; - goto fail; - } - ERROR("%s", "This new key will be written on disk for further usage. " - "do you agree ?"); - if (!fgets(buf, sizeof(buf), stdin)) { - ret = -1; - goto fail; - } - if (strncasecmp(buf, "yes", 3) == 0) { - if (ssh_write_knownhost(blksession) < 0) { - ERROR("%s", strerror(errno)); - ret = -1; - goto fail; - } - } - break; - - case SSH_SERVER_ERROR: - ERROR("%s", ssh_get_error(blksession)); - ret = -1; - goto fail; - } - - ret = 0; - - fail: - ssh_clean_pubkey_hash(&hash); - - return ret; -} - - -static ssh_session -glusterBlockSSHConnect(const char *host, const char *user, int verbosity) -{ - int auth = 0; - ssh_session blksession; - - blksession = ssh_new(); - if (!blksession) - return NULL; - - if (user) { - if (ssh_options_set(blksession, SSH_OPTIONS_USER, user) < 0) - goto sfree; - } - - if (ssh_options_set(blksession, SSH_OPTIONS_HOST, host) < 0) - goto sfree; - - ssh_options_set(blksession, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); - if (ssh_connect(blksession)) { - ERROR("Connection failed : %s", ssh_get_error(blksession)); - goto sdnt; - } - - if (glusterBlockSSHVerifyKnownHost(blksession)<0) - goto sdnt; - - auth = glusterBlockSSHAuthConsole(blksession); - if (auth == SSH_AUTH_SUCCESS) { - return blksession; - } else if (auth == SSH_AUTH_DENIED) { - ERROR("%s", "Authentication failed"); - } else { - ERROR("while authenticating : %s", ssh_get_error(blksession)); - } - - sdnt: - ssh_disconnect(blksession); - - sfree: - ssh_free(blksession); - - return NULL; -} - - -char * -glusterBlockSSHRun(char *host, char *cmd, bool console) -{ - FILE *fd = NULL; - int ret; - int nbytes; - int rc; - uuid_t out; - char uuid[256]; - char *file; - char buffer[256]; - ssh_session blksession; - ssh_channel blkchannel; - - blksession = glusterBlockSSHConnect(host, NULL/*user*/, 0); - if (!blksession) { - ssh_finalize(); - return NULL; - } - - blkchannel = ssh_channel_new(blksession); - if (!blkchannel) { - ret = 1; - goto chfail; - } - - rc = ssh_channel_open_session(blkchannel); - if (rc < 0) { - ret = 1; - goto fail; - } - - rc = ssh_channel_request_exec(blkchannel, cmd); - if (rc < 0) { - ret = 1; - goto fail; - } - - if (!console) { - uuid_generate(out); - uuid_unparse(out, uuid); - asprintf(&file, "/tmp/%s", uuid); - fd = fopen(file, "w"); - } - - nbytes = ssh_channel_read(blkchannel, buffer, sizeof(buffer), 0); - while (nbytes > 0) { - if (fwrite(buffer, 1, nbytes, fd ? fd : stdout) != (unsigned int) nbytes) { - ret = 1; - goto fail; - } - nbytes = ssh_channel_read(blkchannel, buffer, sizeof(buffer), 0); - } - - if (nbytes < 0) { - ret = 1; - goto fail; - } - - ssh_channel_send_eof(blkchannel); - ret = 0; - - if (console && ret == 0) - file = "stdout"; /* just to differentiate b/w success and failure */ - - fail: - if (!console) - fclose(fd); - - ssh_channel_close(blkchannel); - ssh_channel_free(blkchannel); - - chfail: - ssh_disconnect(blksession); - ssh_free(blksession); - ssh_finalize(); - - return (!ret) ? file : NULL; -} diff --git a/ssh-common.h b/ssh-common.h deleted file mode 100644 index 57c7f9d..0000000 --- a/ssh-common.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# ifndef _SSH_COMMON_H -# define _SSH_COMMON_H 1 - -# include <libssh/libssh.h> - - - -char * -glusterBlockSSHRun(char *host, char *cmd, bool console); - -#endif /* _SSH_COMMON_H */ @@ -46,9 +46,6 @@ gbFree(void *ptrptr) { int save_errno = errno; - if(*(void**)ptrptr) - return; - free(*(void**)ptrptr); *(void**)ptrptr = NULL; errno = save_errno; |