/* * Secure X Message Passing Library v2 examples. * * (c) Originally written by somebody else ... * (c) Alexander Vdolainen 2013-2015 * * 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 master or simply - daemon part, it will * listen a requests and create a stream with directory entries, * which ridden by the client. * Using the builtin stream functionality added since 0.4.2 version. * * This implements a simple client-server topology, to see * more advanced technics check out other examples. * * 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 "filelist.h" #include "helpers.h" #include "../config.h" #define FULL_PROGRAM_NAME "File lister master (builtin streams based)" /* firstly we need to take an rpc calls data, * sxmp uses usrtc from libtdata to store it */ static usrtc_t *fulist; /* ok, here we will define out sxmp specific functions */ /* * RPC list contain groups of RPC calls called channel types * for each sxmp link depends on access rules you can change * available channel types. * To do so you must provide a special callback returning this list. * Since we haven't any access restrictions in our example, just * create a fake. */ static usrtc_t *__rettlist(sxlink_t *l) { return fulist; } /* * Each sxmp link validated by certificate ID, * i.e. when basic checking is done, you can also * review the certificate ID, for example you need * to disable certificate for a time being. * * Here we don't have those checks, just always accept */ static int __validate_sslpem(sxlink_t *l) { return 0; } /* * To be more paranoic, sxmp also allow to * check up username and password. * We don't overview this tuff here, just * always allow. */ static int __secure_check(sxlink_t *l) { return SXE_SUCCESS; } /* misc functions */ static int __ping(void *m, sexp_t *sx) { return sxmsg_return((sxmsg_t*)m, SXE_SUCCESS); } /* command line options helpers */ static void __help_print(FILE *fso, const char *fmtname) { fprintf(fso, "\n%s\n\n", FULL_PROGRAM_NAME); /* usage options */ fprintf(fso, "Usage:\n"); fprintf(fso, "\t%s -r | --root-x509 -u | --master-x509 " " [-p | --listen-port ]\n", fmtname); /* 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 host X.509 public and private certificate.\n", "-m | --master-x509 "); fprintf(fso, "\t%-33s Remote host listening port number [default: %d].\n", "-p | --listen-port ", DEFAULT_PORT); fprintf(fso, "\t%-33s Show help screen.\n", "-h | --help"); fprintf(fso, "\t%-33s Print version information.\n", "-v | --version"); return; } static void __version_print(FILE *fso) { fprintf(fso, "\nFile list example master daemon (builtin streams).\n"); fprintf(fso, "Examples bundle for %s %s.\n", PACKAGE_NAME, PACKAGE_VERSION); return; } int main(int argc, char **argv) { char *rootca = NULL, *cert = NULL; sxhub_t *sxmphub = sxhub_create(); int port = DEFAULT_PORT; int opt; while(1) { int option_index = 0; static struct option long_options[] = { /* These options a generic ones. */ {"help", no_argument, NULL, 'h'}, /* print out help and version info */ {"version", no_argument, NULL, 'v'}, /* just out a version info */ /* The following options about settings . */ {"root-x509", required_argument, NULL, 'r'}, {"master-x509", required_argument, NULL, 'm'}, {"listen-port", required_argument, NULL, 'p'}, { NULL, 0, NULL, 0 }, }; if((opt = getopt_long(argc, argv, "hvr:m:", 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))) return ENOMEM; break; case 'm': if(!(cert = strdup(optarg))) return ENOMEM; break; case 'p': port = atoi(optarg); break; } } if(!rootca) { fprintf(stderr, "Root CA not pointed.\n Failure.\n"); __help_print(stderr, argv[0]); return EINVAL; } if(!cert) { fprintf(stderr, "User certificate not pointed.\n Failure.\n"); __help_print(stderr, argv[0]); return EINVAL; } sxmp_init(); /* all is fine let's init connection subsystem */ if(!sxmphub) { fprintf(stderr, "Subsystem init failed: %d\n", opt); return 2; } /* set working certificates */ opt = sxhub_setsslserts(sxmphub, rootca, cert, cert); if(opt) { fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt); return opt; } /* clean up */ free(rootca); free(cert); /* set important callbacks to do the security checking */ sxhub_set_authcheck(sxmphub, __secure_check); sxhub_set_sslvalidate(sxmphub, __validate_sslpem); /* ok, now we need to construct RPC lists (channels) */ if(!(fulist = malloc(sizeof(usrtc_t)))) { fprintf(stderr, "Cannot allocate memory for RPC lists\n Failure.\n"); return ENOMEM; } opt = sxmp_rpclist_init(fulist); if(opt) { fprintf(stderr, "Failed to init rpc list\n Failure.\n"); return opt; } /* we will add one channel with type id READONLY_CHANNEL for read only operations */ opt = sxmp_rpclist_add(fulist, READONLY_CHANNEL, "Read only operations", NULL); if(opt) { fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); return opt; } /* ok, let's add stream functions */ opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "ping", __ping); if(opt) { __fail: fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); return opt; } /* ok, setup it */ sxhub_set_rpcvalidator(sxmphub, __rettlist); signal(SIGPIPE, SIG_IGN); /* now we're ready to run the listen process */ int srv = openlistener_socket(port); while(1) { struct sockaddr_in addr; socklen_t len = sizeof(addr); sxlink_t *link; int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */ link = sxlink_master_accept(sxmphub, client, NULL); if(!link) fprintf(stderr, "Cannot create sxmp link (%d)\n", errno); } sxhub_destroy(sxmphub); sxmp_finalize(); return 0; }