/* * Secure Network Transport Layer Library v2 implementation. * (sntllv2) it superseed all versions before due to the: * - memory consumption * - new features such as pulse emitting * - performance optimization * * This is a proprietary software. See COPYING for further details. * * (c) Askele Group 2013-2015 * */ #include #define __USE_GNU #include #include #include #ifdef WIN32 #include #include #include #else #include #include #include #include #include #include #include #include #include #endif #include #include #include #include #include // #include #include #include #include /* helper functions */ int __openlistener(int port) { int sd; struct sockaddr_in addr; sd = socket(PF_INET, SOCK_STREAM, 0); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) { perror("can't bind port"); abort(); } if ( listen(sd, 10) != 0 ) { perror("Can't configure listening port"); abort(); } return sd; } /* * Validation of the SSL certificate * this function must be exist. */ static int __validate_sslpem(conn_t *co) { return 0; } /* * validate - authorize user with password */ static int __secure_check(conn_t *co) { return SNE_SUCCESS; } /* * typed list callback */ static int __set_typed_list_callback(conn_t *co, int ch, char *desc) { printf("allowed channel %d (%s)\n", ch, desc); return 0; } /* list of rpc calls functions */ usrtc_t *fulist; /* our fake */ usrtc_t *__rettlist(conn_t *c) { return fulist; } /* RPC functions implementation */ static int __ar_add(void *m, sexp_t *sx) { sexp_t *lsx = NULL, *sx_iter; sxmsg_t *msg = (sxmsg_t *)m; char *buf; int idx; size_t ln = 0; if(sexp_list_cdr(sx, &lsx)) { printf("Invalid protocol\n"); return sxmsg_return(msg, SNE_BADPROTO); } long int sum = 0; SEXP_ITERATE_LIST(lsx, sx_iter, idx) { if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { fprintf(stderr, "Invalid value type\n"); return sxmsg_return(msg, SNE_BADPROTO); } sum += atoi(sx_iter->val); } buf = sxmsg_rapidbuf(msg); ln = snprintf(buf, MAX_RBBUF_LEN, "(add-result %ld)", sum); return sxmsg_rreply(msg, ln); } static int __ar_multiply(void *data, sexp_t *sx) { sexp_t *lsx = NULL; sxmsg_t *msg = (sxmsg_t *)data; char *buf; int idx; sexp_t *sx_iter; size_t ln; if(sexp_list_cdr(sx, &lsx)) { printf("Invalid protocol\n"); return sxmsg_return(msg, SNE_BADPROTO); } long int mult = 0; SEXP_ITERATE_LIST(lsx, sx_iter, idx) { if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) { printf("Invalid value type\n"); return sxmsg_return(msg, SNE_BADPROTO); } mult *= atoi(sx_iter->val); } buf = sxmsg_rapidbuf(msg); ln = snprintf(buf, MAX_RBBUF_LEN, "(multiply-result %ld)", mult); return sxmsg_rreply(msg, ln); } /* define a little bit */ #define DEFAULT_PORT 13133 static void sigpipe_handler(int a) { return; } int main(int argc, char **argv) { // set detailed signal handler // struct sigaction sigact, sigpipe; // sigact.sa_flags = SA_SIGINFO; // sigact.sa_sigaction = signal_error; // sigemptyset(&sigact.sa_mask); // sigaction(SIGFPE, &sigact, 0); // sigaction(SIGILL, &sigact, 0); // sigaction(SIGSEGV, &sigact, 0); // sigaction(SIGBUS, &sigact, 0); // memset(&sigpipe, 0, sizeof(struct sigaction)); // sigpipe.sa_handler = sigpipe_handler; // sigaction(SIGPIPE, &sigpipe, NULL); char *rootca = NULL, *cert = NULL; conn_sys_t *ssys = connections_create(); int port = DEFAULT_PORT; int opt; while((opt = getopt(argc, argv, "p:r:u:")) != -1) { switch(opt) { case 'p': port = atoi(optarg); break; case 'r': rootca = strdup(optarg); break; case 'u': cert = strdup(optarg); break; default: fprintf(stderr, "usage: %s [-p ] -r -u \n", argv[0]); return EINVAL; } } if(!rootca) { fprintf(stderr, "Root CA not pointed.\n Failure.\n"); return EINVAL; } if(!cert) { fprintf(stderr, "User certificate not pointed.\n Failure.\n"); return EINVAL; } sntl_init(); /* all is fine let's init connection subsystem */ if(!ssys) { fprintf(stderr, "Subsystem init failed: %d\n", opt); return 2; } /* set wroking certificates */ opt = connections_setsslserts(ssys, 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 */ connections_set_authcheck(ssys, __secure_check); connections_set_sslvalidate(ssys, __validate_sslpem); /* set a callback, it's optional and doesn't required in server side apps */ connections_set_channelcall(ssys, __set_typed_list_callback); /* 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 = sntl_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 12 "Demo rpc list" */ opt = sntl_rpclist_add(fulist, 12, "Demo RPC list", NULL); if(opt) { fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); return opt; } /* ok, let's add two functions */ opt = sntl_rpclist_add_function(fulist, 12, "ar-add", __ar_add); if(opt) { __fail: fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); return opt; } opt = sntl_rpclist_add_function(fulist, 12, "ar-multiply", __ar_multiply); if(opt) goto __fail; /* ok, setup it */ connections_set_rpcvalidator(ssys, __rettlist); /* now we're ready to run the listen process */ int srv = __openlistener(port); while(1) { struct sockaddr_in addr; socklen_t len = sizeof(addr); conn_t *co; int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */ co = connection_master_link(ssys, client, NULL); /* create connection, that's all */ if(!co) { fprintf(stderr, "Cannot create connetion (%d)\n", opt); } } return 0; }