From 54484937649acabe79b9cda01dea023521da9745 Mon Sep 17 00:00:00 2001 From: Alexander Vdolainen Date: Fri, 4 Mar 2016 02:01:10 +0200 Subject: [PATCH] [examples] added autoconf stubs for smpf example i.e. new option to configure added, because this example require readline library; --- configure.ac | 24 ++++ examples/.gitignore | 2 + examples/Makefile.am | 12 +- examples/smpfd.c | 303 ++++++++++++++++++++++++++++++++++++++++++ examples/smpfd_defs.h | 11 +- 5 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 examples/smpfd.c diff --git a/configure.ac b/configure.ac index cafdf35..b04398d 100644 --- a/configure.ac +++ b/configure.ac @@ -16,6 +16,7 @@ dnl ***************** dnl ***** options ***** dnl ***************** +dnl Build basic examples option AC_ARG_ENABLE([build_examples], AS_HELP_STRING([--enable-build-examples], [Enable examples build])) @@ -25,6 +26,19 @@ AS_IF([test "x$enable_build_examples" = "xyes"], [ AM_CONDITIONAL(BUILD_EXAMPLES, test "x$enable_build_examples" = "xyes") +dnl Build smpf example daemon and client option +AC_ARG_ENABLE([build_smpf_example], + AS_HELP_STRING([--enable-build-smpf-example], [Enable to build smpf advanced example, requires readline])) + +AS_IF([test "x$enable_build_smpf_example" = "xyes"], [ + AC_DEFINE([BUILD_SMPF_EXAMPLE], 1, [build of smpf example enabled]) +]) + +AM_CONDITIONAL(BUILD_SMPF_EXAMPLE, test "x$enable_build_smpf_example" = "xyes") + + +dnl checking fpr dependencies + PKG_CHECK_MODULES(OPENSSL, [openssl]) PKG_CHECK_MODULES(LIBTDATA, [libtdata >= 0.2.2]) @@ -40,6 +54,16 @@ case $host_os in LINUX=no;; esac +case $enable_build_smpf_example in + yes) + sic_save_LIBS=$LIBS + AC_CHECK_LIB(readline, readline) + if test x"${ac_cv_lib_readline_readline}" = xno; then + AC_MSG_ERROR(libreadline not found) + fi + LIBS=$sic_save_LIBS + ;; +esac AM_CONDITIONAL(COND_WIN32, test "x$WIN32" = "xyes") diff --git a/examples/.gitignore b/examples/.gitignore index 82bf854..faa5383 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -2,3 +2,5 @@ filelistc filelistd streamfld streamflc +smpfd +smpfc diff --git a/examples/Makefile.am b/examples/Makefile.am index 966fcd9..196a71f 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -13,7 +13,13 @@ AM_CFLAGS = -Wall -g # where to find libsxmp libsxmp = ../lib/.libs/libsxmp.la -bin_PROGRAMS = filelistd filelistc streamfld streamflc +if BUILD_SMPF_EXAMPLE +smpf_programs = smpfd +else +smpf_programs = +endif + +bin_PROGRAMS = filelistd filelistc streamfld streamflc $(smpf_programs) filelistd_SOURCES = helpers.c filelistd.c filelistd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ @@ -30,3 +36,7 @@ streamfld_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ streamflc_SOURCES = streamflc.c streamflc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ $(LIBUUID_LIBS) $(libsxmp) -lpthread + +smpfd_SOURCES = helpers.c smpfd.c +smpfd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \ + $(LIBUUID_LIBS) $(libsxmp) -lpthread diff --git a/examples/smpfd.c b/examples/smpfd.c new file mode 100644 index 0000000..ae16a07 --- /dev/null +++ b/examples/smpfd.c @@ -0,0 +1,303 @@ +/* + * Secure X Message Passing Library v2 examples. + * + * (c) Alexander Vdolainen 2013-2015 + * (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 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 + +#include "helpers.h" +#include "smpf.h" +#include "smpfd_defs.h" +#include "../config.h" + +#define FULL_PROGRAM_NAME "SMPF (secure message passing file) daemon" + +static struct smpfd_ctx daemon_ctx; + +/* 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; +} + +/* remote functions implementation */ +/* 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 ] [-R | --root-dir ]\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 Remote directory becoming root for user [default: %s].\n", + "-R | --root-dir ", DEFAULT_ROOT_DIR); + 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, "\n%s.\n", FULL_PROGRAM_NAME); + fprintf(fso, "Examples bundle for %s %s.\n", PACKAGE_NAME, PACKAGE_VERSION); + return; +} + +int main(int argc, char **argv) +{ + char *rootca = NULL, *cert = NULL; + char *root_dir = 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'}, + {"root-dir", required_argument, NULL, 'R'}, + {"listen-port", required_argument, NULL, 'p'}, + { NULL, 0, NULL, 0 }, + }; + + if((opt = getopt_long(argc, argv, "hvr:m:R:p:", 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; + case 'R': + root_dir = strdup(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; + } + /* root directory */ + if(!root_dir) { + root_dir = strdup(DEFAULT_ROOT_DIR); + if(!root_dir) { + fprintf(stderr, "Not enough memory.\n"); + 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); + free(root_dir); + + /* 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) { + fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); + return opt; + } + + /* ok, setup it */ + sxhub_set_rpcvalidator(sxmphub, __rettlist); + + /* setup our stream */ + // sxhub_stream_register(sxmphub, &dirlist_stream); + + 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; +} diff --git a/examples/smpfd_defs.h b/examples/smpfd_defs.h index ffc8bc6..62d4b3c 100644 --- a/examples/smpfd_defs.h +++ b/examples/smpfd_defs.h @@ -21,9 +21,12 @@ #ifndef __SXMP_EXAMPLES_SMPFD_DEFS_H__ #define __SXMP_EXAMPLES_SMPFD_DEFS_H__ +struct mp_fnode; + struct smpfd_ctx { char *hostname; char *root_dir; + struct mp_fnode *root; }; struct mp_session { @@ -36,6 +39,11 @@ typedef enum { DIRECTORY, } fnode_type_t; +struct mp_pcache_t { + list_head_t *pg; + size_t size; +}; + struct mp_fnode { int fd; uid_t uid; @@ -47,9 +55,10 @@ struct mp_fnode { fnode_type_t type; struct mp_fnode *parent; union { - mp_pcache_t *bcache; + struct mp_pcache_t *bcache; list_head_t *dcache; }; + pthread_mutex_t lock; };