/* * Secure X Message Passing Library v2 examples. * * (c) Alexander Vdolainen 2016 * * libsxmp is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libsxmp 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 Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see ."; * */ /* * This is an example of sxmp usage. * NOTE: It was developed quite fast within one day, * btw - this the reason of some ugly code here. * * This is a client example for filelister implemented * using builtin streams, available since 0.4.2 * * NOTE(win32): don't have a time to test it or fix it to * make it works on windows, if you can - u're welcome. */ #include #include #define __USE_GNU #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "filelist.h" #include "../config.h" #define FULL_PROGRAM_NAME "File lister client (builtin streams based)" #include "helpers.h" struct _remote_host { char *root_x509; char *user_x509; char *hostname; char *login; char *password; int port; sxhub_t *hub; sxlink_t *link; }; struct _astream { int tid; char *longcmd; char *short_option; char *description; void (*print_head)(FILE *); void (*print_op)(FILE *, list_head_t *); int (*exefoo)(FILE *, struct _remote_host *, struct _astream *, const char *); }; static void __dirlist_headout(FILE *); static void __dirlist_out(FILE *, list_head_t *); static int __dirlist(FILE *, struct _remote_host *, struct _astream *, const char *); struct _astream streams_source[] = { { .tid = DIRLIST_ID, .longcmd = "dir-list", .short_option = "e", .print_head = __dirlist_headout, .print_op = __dirlist_out, .exefoo = __dirlist, .description = "List directory contents on remote host" }, { .tid = 0, .longcmd = NULL, .short_option = NULL, .print_head = NULL, .print_op = NULL, .exefoo = NULL, .description = NULL }, }; /* * dir listing from remote host goes below. */ /* printing */ static void __dirlist_headout(FILE *f) { fprintf(f, "%-24s | %-12s\n", "Name", "Type"); fprintf(f, "---------------------------------------\n"); return; } static void __dirlist_out(FILE *f, list_head_t *list) { char *dname = NULL, *dtype = NULL; list_node_t *iter, *siter; struct _nn_stream_entry_node *entry; int i = 0; list_for_each_safe(list, iter, siter) { entry = list_entry(iter, struct _nn_stream_entry_node, node); if(!i) dname = entry->value; else if(i == 1) dtype = entry->value; i++; } fprintf(f, "%-24s | %-12s\n", dname, dtype); return; } /* command itself */ static int __dirlist(FILE *f, struct _remote_host *remote, struct _astream *rstream, const char *opt) { sxlink_t *link = remote->link; int stream_tid = rstream->tid; sxstream_t *stream; list_head_t *list; rstream->print_head(f); stream = sxstream_open(link, opt, stream_tid, SXE_O_READ); if(!stream) { fprintf(stderr, "Failed to open stream with %d ID (%d).\n", stream_tid, errno); return EINVAL; } while((list = sxstream_read(stream)) != NULL) rstream->print_op(f, list); if(errno != SXE_EOS) { fprintf(stderr, "Reading failed (%d)\n", errno); } sxstream_close(stream); return 0; } /* sxmp stuff below */ static int __rpcscheck_onclient(sxlink_t *l, int ch_tid, char *description) { return SXE_SUCCESS; } static int __remote_host_connect(struct _remote_host *rh) { int r = 0; sxhub_set_channelcall(rh->hub, __rpcscheck_onclient); /* here we go, connect to the hist i.e. create a link to it */ rh->link = sxlink_connect(rh->hub, rh->hostname, rh->port, rh->user_x509, rh->login, rh->password); if(!rh->link) r = errno; return r; } /* standard output helpers */ static void __help_print(FILE *fso, const char *fmtname) { int i; fprintf(fso, "\n%s\n\n", FULL_PROGRAM_NAME); /* usage options */ fprintf(fso, "Usage:\n"); for(i = 0; streams_source[i].longcmd != NULL; i++) { fprintf(fso, "\t%s -r | --root-x509 -u | --user-x509 -H | --hostname " " -l | --login -P | --password -%s | --%s " " [-p | --port ]\n", fmtname, streams_source[i].short_option, streams_source[i].longcmd); } /* defaults */ fprintf(fso, "\t%s -h | --help\n", fmtname); fprintf(fso, "\t%s -v | --version\n", fmtname); /* options description */ fprintf(fso, "\nOptions:\n"); fprintf(fso, "\t%-33s Set pathname of the remote root X.509 public certificate.\n", "-r | --root-x509 "); fprintf(fso, "\t%-33s Set pathname of the user X.509 public and private certificate.\n", "-u | --user-x509 "); fprintf(fso, "\t%-33s Hostname or IP address of the remote host.\n", "-H | --hostname "); fprintf(fso, "\t%-33s Set remote login name.\n", "-l | --login "); fprintf(fso, "\t%-33s Set remote user password.\n", "-P | --password "); fprintf(fso, "\t%-33s Remote host listening port number [default: %d].\n", "-p | --port ", DEFAULT_PORT); for(i = 0; streams_source[i].longcmd != NULL; i++) { fprintf(fso, "\t-%-2s| --%-26s %s.\n", streams_source[i].short_option, streams_source[i].longcmd, streams_source[i].description); } fprintf(fso, "\t%-33s Show help screen.\n", "-h | --help"); fprintf(fso, "\t%-33s Print version information.\n", "-v | --version"); return; } #define GENERIC_OPTS "hvr:u:H:p:l:P:" static struct option o_help = {"help", no_argument, NULL, 'h'}; static struct option o_version = {"version", no_argument, NULL, 'v'}; static struct option o_rootx509 = {"root-x509", required_argument, NULL, 'r'}; static struct option o_userx509 = {"user-x509", required_argument, NULL, 'u'}; static struct option o_hostname = {"hostname", required_argument, NULL, 'H'}; static struct option o_port = {"port", required_argument, NULL, 'p'}; static struct option o_login = {"login", required_argument, NULL, 'l'}; static struct option o_password = {"password", required_argument, NULL, 'P'}; int main(int argc, char **argv) { char *rootca, *cert, *host, *login, *password; char *options, *argument = NULL; int port = DEFAULT_PORT, opt, i = 0, opt_len = 9, r = 0; struct _remote_host *rh = malloc(sizeof(struct _remote_host)); sxhub_t *lhub; struct _astream *src = NULL; int (*execution)(FILE *, struct _remote_host *, struct _astream *, const char *); static struct option *long_options; if(!rh) return ENOMEM; else memset(rh, 0, sizeof(struct _remote_host)); rootca = cert = host = login = password = NULL; execution = NULL; /* amount of builtin commands */ for(i = 0; streams_source[i].longcmd != NULL; i++) ;; opt_len += i; /* generate options string */ if(!(options = malloc(strlen(GENERIC_OPTS) + sizeof(char)*((i*2) + 1)))) { free(rh); return ENOMEM; } else memset(options, 0, strlen(GENERIC_OPTS) + sizeof(char)*((i*2) + 1)); strcat(options, GENERIC_OPTS); for(i = 0; streams_source[i].longcmd != NULL; i++) { strcat(options, streams_source[i].short_option); strcat(options, ":"); } /* generate long options */ long_options = malloc(sizeof(struct option)*opt_len); if(!long_options) { free(options); free(rh); return ENOMEM; } else memset(long_options, 0, sizeof(struct option)*opt_len); for(i = 0; i < opt_len; i++) { switch(i) { case 0: long_options[i] = o_help; break; case 1: long_options[i] = o_version; break; case 2: long_options[i] = o_rootx509; break; case 3: long_options[i] = o_userx509; break; case 4: long_options[i] = o_hostname; break; case 5: long_options[i] = o_port; break; case 6: long_options[i] = o_login; break; case 7: long_options[i] = o_password; break; default: if(i == (opt_len - 1)) memset(&long_options[i], 0, sizeof(struct option)); else { long_options[i].name = streams_source[i - 8].longcmd; long_options[i].has_arg = required_argument; long_options[i].flag = NULL; long_options[i].val = *(streams_source[i - 8].short_option); } break; } } r = ENOMEM; while(1) { int option_index = 0; if((opt = getopt_long(argc, argv, (const char *)options, long_options, &option_index)) == -1) break; switch(opt) { case 'h': __help_print(stdout, argv[0]); return 0; break; case 'v': version_print(stdout); return 0; break; case 'r': if(!(rootca = strdup(optarg))) goto __failsafe; break; case 'u': if(!(cert = strdup(optarg))) goto __failsafe; break; case 'H': if(!(host = strdup(optarg))) goto __failsafe; break; case 'l': if(!(login = strdup(optarg))) goto __failsafe; break; case 'P': if(!(password = strdup(optarg))) goto __failsafe; break; case 'p': port = atoi(optarg); break; default: for(i = 0; streams_source[i].longcmd != NULL; i++) { if(*(streams_source[i].short_option) == (char)opt) { if(!execution) { src = &streams_source[i]; argument = strdup(optarg); execution = streams_source[i].exefoo; } else { r = EINVAL; fprintf(stderr, "One command at once only.\n"); __help_print(stderr, argv[0]); __failsafe: free(options); if(argument) free(argument); free(long_options); free(rh); return r; } } } if(!execution) { r = EINVAL; goto __failsafe; } break; } } /* ok validate all before doing any stuff */ if(!rootca || !cert) { fprintf(stderr, "One or more x.509 certificates files not pointed.\n"); __help_print(stderr, argv[0]); return EINVAL; } if(!login || !password) { fprintf(stderr, "Login or password not pointed.\n"); __help_print(stderr, argv[0]); return EINVAL; } if(port <= 0) { fprintf(stderr, "Port number has invalid value.\n"); __help_print(stderr, argv[0]); return EINVAL; } if(!execution) { fprintf(stderr, "No command given.\n"); __help_print(stderr, argv[0]); return EINVAL; } /* looks good */ sxmp_init(); /* init library */ lhub = sxhub_create(); /* create sxhub for link creation */ if(!lhub) { r = ENOMEM; goto __failsafe; } r = sxhub_setsslserts(lhub, rootca, cert, cert); if(r) goto __failsafe; /* ok setup our structure */ rh->port = port; rh->root_x509 = rootca; rh->user_x509 = cert; rh->hostname = host; rh->login = login; rh->password = password; rh->hub = lhub; if((r = __remote_host_connect(rh))) { fprintf(stderr, "Failed to create link to %s@%s:%d with %d.\n", rh->login, rh->hostname, rh->port, r); } else { r = execution(stdout, rh, src, argument); sxlink_close(rh->link); } /* free all stuff */ free(options); free(long_options); if(rh->root_x509) free(rh->root_x509); if(rh->user_x509) free(rh->user_x509); if(rh->hostname) free(rh->hostname); if(rh->password) free(rh->password); if(rh->login) free(rh->login); free(rh); if(lhub) sxhub_destroy(lhub); return r; }