static int verify_callback(int preverify_ok, X509_STORE_CTX * x509ctx) { X509_NAME *xn; static char txt[256]; xn = X509_get_subject_name(x509ctx->current_cert); X509_NAME_oneline(xn, txt, sizeof(txt)); if (preverify_ok == 0) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"SSL verify error: depth=%d error=%s cert=%s", x509ctx->error_depth, X509_verify_cert_error_string(x509ctx->error), txt); return 0; } /* * the check against allowed clients are done elsewhere */ LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"SSL authenticated peer: %s\n", txt); return 1; /* accept */ }
/*! * \brief if necessary libraries are present this function converts the input * to utf8 and normalizes it. * \param s The input string * \return Returns a newly allocated zero-terminated string. */ char *normalize( char *s ) { char *buf; #ifdef HAVE_LIBIDN int bufsize, rc; char *utf8; traceLog(LOG_INFO,"Doing stringprep on %s", s); /* stringprep_locale_charset(); */ utf8 = stringprep_locale_to_utf8(s); bufsize = strlen(utf8) * 2; buf = (char *) Malloc ( bufsize * sizeof( char ) ); strcpy(buf,utf8); rc = stringprep (buf, bufsize, 0, stringprep_nameprep); if (rc != STRINGPREP_OK) { traceLog(LOG_INFO,"Stringprep failed with rc %d", rc); Free(buf); buf = utf8; } else Free(utf8); traceLog(LOG_INFO,"result %s", buf); #else buf = Strdup(s); #endif return buf; }
int rm_endofrule(junc_t * jp, element_t * ep, ruleinst_t * rt) { branch_t *bp; spocp_index_t *inx; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"rm end_of_rule"); bp = ARRFIND(jp, SPOC_ENDOFRULE); bp->count--; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"Branch count=%d", bp->count); inx = bp->val.id; index_rm(inx, rt); if (inx->n == 0) { branch_free(bp); return 0; } /* * there is no next element */ return 1; }
spocp_result_t get_rules( srv_t *srv ) { spocp_result_t rc = SPOCP_SUCCESS; int nrules = 0, r; dbcmd_t dbc; struct timeval start, end; memset( &dbc, 0, sizeof( dbcmd_t )); dbc.dback = srv->dback; if (srv->dback) { /* * does the persistent database store need any initialization * ?? * if( srv.dback->init ) srv.dback->init( dbcmd_t *dbc ) * ; */ if ((nrules = dback_read_rules(&dbc, srv, &rc)) < 0) return rc; } if (nrules == 0) { if (srv->rulefile) { LOG(SPOCP_INFO) traceLog(LOG_INFO, "Opening rules file \"%s\"", srv->rulefile); if (0) gettimeofday(&start, NULL); /* dbc.dback = srv->dback; dbc.handle = 0; */ r = read_rules(srv, srv->rulefile, &dbc) ; if( r == -1 ) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error while reading rules"); rc = SPOCP_OPERATIONSERROR; } if (0) { gettimeofday(&end, NULL); print_elapsed("readrule time:", start, end); } } else LOG(SPOCP_INFO) traceLog(LOG_INFO, "No rule file to start with"); } else { LOG(SPOCP_INFO) traceLog(LOG_INFO, "Got the rules from the persistent store, will not read the rulefile"); } return rc; }
spocp_result_t is_ipv4(octet_t * op, struct in_addr * ia) { char c; c = op->val[op->len]; op->val[op->len] = 0; #ifdef HAVE_INET_NTOP if (inet_pton(AF_INET, op->val, ia) <= 0) { #else if (inet_aton( op->val, ia) == 0) { #endif op->val[op->len] = c; traceLog(LOG_ERR,"Error in IP number definition: %s", strerror(errno)); return SPOCP_SYNTAXERROR; } else { op->val[op->len] = c; ia->s_addr = htonl( ia->s_addr ); return SPOCP_SUCCESS; } } spocp_result_t is_ipv4_s(char *ip, struct in_addr * ia) { #ifdef HAVE_INET_NTOP if (inet_pton(AF_INET, ip, ia) <= 0) #else if (inet_aton( ip, ia) == 0) #endif return SPOCP_SYNTAXERROR; else return SPOCP_SUCCESS; } #ifdef USE_IPV6 spocp_result_t is_ipv6(octet_t * op, struct in6_addr * ia) { char c; c = op->val[op->len]; op->val[op->len] = 0; if (inet_pton(AF_INET6, op->val, ia) <= 0) { op->val[op->len] = c; traceLog(LOG_ERR,"Error in IP number definition: %s", strerror(errno)); return SPOCP_SYNTAXERROR; } else { op->val[op->len] = c; return SPOCP_SUCCESS; } }
static int tls_error(int level, conn_t * conn, char *msg) { char errorstr[1024]; unsigned long e; e = ERR_get_error(); ERR_error_string_n(e, errorstr, 1024); LOG(level) traceLog(LOG_ERR,"TLS error on connection from %s (%s): %s", conn->sri.hostname, conn->sri.hostaddr, msg); LOG(level) traceLog(LOG_ERR,"\"%s\"", errorstr); return FALSE; }
spocp_result_t rule_rm(junc_t * jp, octet_t * rule, ruleinst_t * rt) { element_t *ep = 0; int r = 1; /* default SUCCESS? well sort of */ spocp_result_t rc; octet_t loc; DEBUG(SPOCP_DSTORE) { oct_print(LOG_DEBUG,"- rm rule", rule); } /* * decouple */ loc.val = rule->val; loc.len = rule->len; if ((rc = element_get(&loc, &ep)) != SPOCP_SUCCESS) return rc; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"---"); if (ep) { r = element_rm(jp, ep, rt); } if (r == 1) return SPOCP_SUCCESS; else return SPOCP_OPERATIONSERROR; }
int list_rm(branch_t * bp, element_t * ep, ruleinst_t * rt) { element_t *elemp; list_t *lp = ep->e.list; junc_t *njp = bp->val.list; int r; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"rm list"); elemp = lp->head; r = element_rm(njp, elemp, rt); /* * DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG, "rm list; is there anything more?") ; * * if( r == 0 ) { njp->item[ elemp->type ] = 0 ; * * if( junction_index( njp ) == 0 ) { junc_free( njp ) ; bp->val.list * = 0 ; } } */ return 1; }
static bcspec_t * bcspec_new(plugin_t * plt, octet_t * spec) { octet_t oct; bcspec_t *bcs = 0; plugin_t *p; int n; /* * two parts name ":" typespec */ if ((n = octchr(spec, ':')) < 0) { oct_print( LOG_ERR, "Error in boundary condition specification", spec); return 0; } oct.len = spec->len - n - 1; oct.val = spec->val + n + 1; spec->len = n; if ((p = plugin_match(plt, spec)) == 0) { traceLog(LOG_ERR,"Doesn't match any known plugin",spec); return 0; } bcs = (bcspec_t *) Calloc(1,sizeof(bcspec_t)); bcs->plugin = p; bcs->name = oct2strdup(spec, 0); bcs->spec = octdup(&oct); return bcs; }
static int ssn_rm(branch_t * bp, ssn_t * ssn, char *sp, int direction, element_t * ep, ruleinst_t * rt) { junc_t *jp; int r; jp = ssn_delete(&ssn, sp, direction); if (ssn == 0) { branch_free(bp); return 0; } if (jp) { r = rm_next(jp, ep, rt); if (r == 0) { /* one branch gone from the junction */ /* * could this really happen ?? */ if (junction_index(jp) == 0) { DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG, "Junction without any branches"); junc_free(jp); return -1; } } } return 1; }
int range_rm(branch_t * bp, element_t * ep, ruleinst_t * rt) { junc_t *jp; int rc, dtype = ep->e.range->lower.type & 0x07; jp = sl_range_rm(bp->val.range[dtype], ep->e.range, &rc); if (rc == 1) { junc_free(jp); branch_free(bp); return 0; } rc = rm_next(jp, ep, rt); if (rc == 0) { /* one branch gone from the junction */ /* * could this really happen ?? */ if (junction_index(jp) == 0) { DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"Junction without any branches"); junc_free(jp); return -1; } } return 1; }
LONG CALLBACK MJCore_Exception_Filter(_EXCEPTION_POINTERS *ex) { CodeConv::tostringstream dmsg, lmsg; #ifdef _MSC_VER PIMAGEHLP_SYMBOL pSymbol; #endif DWORD disp; ErrorInfo *errinf = nullptr; lmsg << _T("ハンドルされていない例外 ") << std::hex << std::setw(8) << std::setfill(_T('0')) << ex->ExceptionRecord->ExceptionCode << _T(" が発生したため、強制終了されます。"); fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); CONTEXT context; memcpy(&context, ex->ContextRecord, sizeof(CONTEXT)); switch (ex->ExceptionRecord->ExceptionCode) { case EXCEPTION_MJCORE_SUBSCRIPT_OUT_OF_RANGE: case EXCEPTION_MJCORE_INVALID_ARGUMENT: case EXCEPTION_MJCORE_INVALID_DATA: case EXCEPTION_MJCORE_OVERFLOW: case EXCEPTION_MJCORE_DECOMPRESSION_FAILURE: case EXCEPTION_MJCORE_HASH_MISMATCH: errinf = (ErrorInfo *)(ex->ExceptionRecord->ExceptionInformation[0]); lmsg << _T(">>> ") << errinf->msg; fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); #if defined(_MSC_VER) && defined(_DEBUG) lmsg << _T(">>> ファイル: ") << errinf->file << _T(" 行: ") << errinf->line << _T(" 関数名: ") << errinf->func; fatal(lmsg.str().c_str()); dmsg << lmsg.str() << std::endl; lmsg.str(_T("")); pSymbol = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 16384); pSymbol->SizeOfStruct = 16384; pSymbol->MaxNameLength = 16384 - sizeof(IMAGEHLP_SYMBOL); SymInitialize(GetCurrentProcess(), nullptr, TRUE); for (unsigned int i = 0; true; i++) { if (i >= ADDRBUF) break; if (errinf->traceBack[i] == 0) break; if (SymGetSymFromAddr(GetCurrentProcess(), errinf->traceBack[i], &disp, pSymbol)) lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << errinf->traceBack[i] << _T(" ") << pSymbol->Name << _T("() + ") << std::setfill(_T('0')) << disp; else lmsg << std::hex << std::setw(8) << std::setfill(_T('0')) << errinf->traceBack[i] << _T(" Unknown"); debug(lmsg.str().c_str()); lmsg.str(_T("")); } SymCleanup(GetCurrentProcess()); GlobalFree(pSymbol); #endif break; #ifdef _MSC_VER default: traceLog(ex->ContextRecord, nullptr, 0); #endif } #ifdef _MSC_VER terminate(); #else abort(); #endif }
static void sig_term( int signo ) { received_sigterm = signo; traceLog(LOG_NOTICE, "Received SIGTERM"); wake_listener(1); }
void rdb_print( void *r ) { int i; varr_t *va; va = rdb_all( r ); if (va) { for( i = 0; i < va->n; i++ ) traceLog( LOG_DEBUG, "RDB %s", ((ruleinst_t *) va->arr[i])->uid); varr_free(va ); } else traceLog( LOG_DEBUG, "RDB EMPTY"); }
static int add_entropy(const char *file) { struct stat st; int n = -1; if (!file) return 0; if (stat(file, &st) == -1) return errno == ENOENT ? 0 : -1; /* * check that the file permissions are secure */ if (st.st_uid != getuid() || ((st.st_mode & (S_IWGRP | S_IRGRP)) != 0) || ((st.st_mode & (S_IWOTH | S_IROTH)) != 0)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"TLS: %s has insecure permissions!", file); return -1; } #ifdef HAVE_RAND_EGD n = RAND_egd(file); #endif if (n <= 0) n = RAND_load_file(file, -1); return n; }
static void element_set_reduce( element_t *ep ) { varr_t *va; size_t i; element_t *te; #ifdef XYDEBUG octet_t *op; char *tmp; op = oct_new( 512, NULL); element_print( op, ep ); tmp = oct2strdup( op, 0 ); traceLog(LOG_DEBUG,"Reducing: [%s]", tmp ); Free( tmp ); #endif varr_rm_dup( ep->e.set, P_element_cmp, P_element_free ); #ifdef XYDEBUG op->len = 0; element_print( op, ep ); tmp = oct2strdup( op, 0 ); traceLog(LOG_DEBUG, "1:st Reduction to [%s]", tmp); Free(tmp); #endif va = ep->e.set; if( va->n > 1 ) { for( i = 0; i < va->n; i++) { if( va->arr[i] == 0 ) continue; te = (element_t *) va->arr[i]; va->arr[i] = element_reduce(te); } } #ifdef XYDEBUG op->len = 0; element_print( op, ep ); tmp = oct2strdup( op, 0 ); traceLog(LOG_DEBUG, "2:nd Reduction to [%s]", tmp); Free(tmp); oct_free( op ); #endif }
/* expects * "what" +SP "=" +SP <base> "/" attr *( ',' attr ) in the configuration * file */ spocp_result_t set_attr( void **vpp, void *cd, int argc, char **argv) { ainfo_t *ai=0, *newai ; char *sp; char *buf; int n; LDAPDN dn = NULL; void *vp; traceLog( LOG_DEBUG, "argc: %d, argv[0]: %s", argc, argv[0]); if( argc != 1 ) return SPOCP_PARAM_ERROR; buf = normalize( argv[0]) ; sp = index( buf, '/' ); if ( !sp) return SPOCP_PARAM_ERROR; *sp++ = '\0'; newai = ( ainfo_t * ) calloc (1, sizeof( ainfo_t )); traceLog( LOG_DEBUG, "Base DN[0]: %s", buf ); ldap_str2dn( buf, &dn, LDAP_DN_FORMAT_LDAPV3); ldap_dn2str( dn, &buf, LDAP_DN_FORMAT_LDAPV3); ldap_memfree( dn ); traceLog( LOG_DEBUG, "Base DN[1]: %s", buf); newai->base = buf; newai->attr = line_split( sp, ',', 0, 1, 0, &n); vp = (void *) newai; if( *vpp != 0 ) { ai = (ainfo_t *) *vpp; newai->next = ai; } *vpp = vp; return SPOCP_SUCCESS; }
int suffix_rm(branch_t * bp, element_t * elemp, ruleinst_t * rt) { atom_t *ap = elemp->e.atom; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"rm suffix \"%s\"", ap->val.val); return ssn_rm(bp, bp->val.suffix, ap->val.val, BACKWARD, elemp, rt); }
int rm_endoflist(junc_t * jp, element_t * ep, ruleinst_t * rt) { branch_t *bp; junc_t *rjp; int r; bp = ARRFIND(jp, SPOC_ENDOFLIST); bp->count--; DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"EOL Branch [%d]", bp->count); rjp = bp->val.list; if (bp->count == 0) { DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"Get rid of the rest of this branch"); branch_free(bp); DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"No type %d branch at this junction any more", SPOC_ENDOFLIST); jp->item[SPOC_ENDOFLIST] = 0; return 0; } r = rm_next(rjp, ep, rt); if (r == 0) { /* one branch gone from the junction */ if (junction_index(rjp) == 0) { DEBUG(SPOCP_DSTORE) traceLog(LOG_DEBUG,"Junction without any branches"); junc_free(rjp); bp->val.list = 0; } } return 1; }
static int generate_eph_rsa_key(SSL_CTX * ctx, int keylength) { RSA *rsa_key; LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Generating %d bit RSA key...\n", keylength); rsa_key = RSA_generate_key(keylength, RSA_F4, NULL, NULL); if (!SSL_CTX_set_tmp_rsa(ctx, rsa_key)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"TLS error (RSA_generate_key): %s", ssl_errstring); return FALSE; } RSA_free(rsa_key); return TRUE; }
static int init_dh(SSL_CTX * ctx, unsigned char *dhparam) { int rc = TRUE; BIO *bio = 0; DH *dh = 0; if (dhparam == NULL) return TRUE; if ((bio = BIO_new_file((char *) dhparam, "r")) == NULL) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"DH: could not read %s: %s", dhparam, strerror(errno)); rc = FALSE; } else { if ((dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) == NULL) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"DH: could not load params from %s", dhparam); rc = FALSE; } else { if (SSL_CTX_set_tmp_dh(ctx, dh) < 0) { LOG(SPOCP_DEBUG) traceLog(LOG_ERR, "Couldn't set Diffie-Hellman parameters"); rc = FALSE; } else LOG(SPOCP_DEBUG) traceLog(LOG_ERR, "Diffie-Hellman initialised from %s with %d-bit key", dhparam, 8 * DH_size(dh)); DH_free(dh); } BIO_free(bio); } return rc; }
void translateException(unsigned int code, _EXCEPTION_POINTERS* ep) { CodeConv::tostringstream lmsg; lmsg << _T("構造化例外 ") << std::hex << std::setw(8) << std::setfill(_T('0')) << ep->ExceptionRecord->ExceptionCode << _T(" をC++例外に変換します。"); info(lmsg.str().c_str()); CONTEXT context; memcpy(&context, ep->ContextRecord, sizeof(CONTEXT)); traceLog(ep->ContextRecord, nullptr, 0); throw ep; }
void StackTraceToArray() { CONTEXT context; memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_FULL; __asm call(x); __asm x: pop eax; __asm mov context.Eip, eax; __asm mov context.Ebp, ebp; __asm mov context.Esp, esp; traceLog(&context, errorInfo.traceBack, sizeof(errorInfo.traceBack)); }
int run_plugin_init(srv_t * srv) { plugin_t *pl; for (pl = srv->plugin; pl; pl = pl->next) { if (strcmp(pl->name, "dback") == 0) continue; if (pl->init) { traceLog(LOG_INFO,"Running the init function for %s", pl->name); pl->init(&pl->conf, &pl->dyn); } } return 0; }
static int password_cb(char *buf, int num, int rwflag, void *userdata) { char *passwd = (char *) userdata; int len; len = (int) strlen(passwd); if (num < len + 1) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Not big enough place for the password (%d)", num); return (0); } strcpy(buf, passwd); return (len); }
static void sig_usr1( int signo ) { struct stat statbuf; work_info_t wi; conn_t *con; traceLog(LOG_NOTICE, "Received SIGUSR1"); stat( srv.rulefile, &statbuf ); if (statbuf.st_mtime != srv.mtime ) { srv.mtime = statbuf.st_mtime; con = conn_new(); con->srv = &srv; con->rs = srv.root; memset( &wi, 0, sizeof( work_info_t )); wi.conn = con; wi.routine = &do_reread_rulefile; reread_rulefile = 1; tpool_add_work( srv.work, &wi); } }
int main(int argc, char **argv) { char buf[BUFSIZ], *cp, *dfile = 0, *subject = 0; int tls = 0, i, transaction = 0, rid = 0; FILE *fp; int res; char *certificate = 0; char *passwd = 0; char *privatekey = 0; char *calist = 0; char *server = 0; char *path, *ruleid, *s; SPOCP *spocp; queres_t qres; spocpc_debug = 0; while ((i = getopt(argc, argv, "dhtTua:c:s:f:p:l:")) != EOF) { switch (i) { case 'a': subject = strdup(optarg); break; case 'c': certificate = strdup(optarg); break; case 'd': spocpc_debug = 1; break; case 'f': dfile = strdup(optarg); break; case 'l': calist = strdup(optarg); break; case 'p': privatekey = strdup(optarg); break; case 's': server = strdup(optarg); break; case 't': tls = 1; break; case 'T': transaction = 1; break; case 'u': rid = 1; break; case 'w': passwd = strdup(optarg); break; case 'h': default: fprintf(stderr, "Usage: %s -s server -f rulefile [-d] [-T] [-a subject] or\n", argv[0]); fprintf(stderr, "%s -t -s server -f rulefile [-d]\n", argv[0]); fprintf(stderr, "\t -c certificate -l calist -p privatekey\n"); fprintf(stderr, "\t -w passwd\n"); exit(0); } } if (server == 0) print_usage(argv[0]); spocp = spocpc_init(server, 0, 0); #ifdef HAVE_SSL if (tls) { spocpc_use_tls(spocp); spocpc_tls_use_cert(spocp, certificate); spocpc_tls_use_calist(spocp, calist); spocpc_tls_use_key(spocp, privatekey); spocpc_tls_use_passwd(spocp, passwd); if (tls & DEMAND) spocpc_tls_set_demand_server_cert(spocp); if (tls & VERIFY) spocpc_tls_set_verify_server_cert(spocp); } #else { fprintf(stderr, "Can't use TLS/SSL, ignoring\n"); tls = 0; } #endif if (spocpc_debug) traceLog(LOG_DEBUG,"Spocpserver [%s]", server); if ((spocp = spocpc_open(spocp, 0, 5)) == 0) { fprintf(stderr, "Could not open connection to \"%s\"\n", server); exit(1); } if (dfile) { if ((fp = fopen(dfile, "r")) == 0) { fprintf(stderr, "Could not open file \"%s\"\n", dfile); exit(1); } } else { if (spocpc_debug) traceLog(LOG_DEBUG,"reading stdin"); fp = stdin; } memset(&qres, 0, sizeof(queres_t)); #ifdef HAVE_SSL if (tls) { if (spocpc_attempt_tls(spocp, &qres) == SPOCPC_OK && qres.rescode == SPOCP_SSL_START) { if (spocpc_start_tls(spocp) == 0) exit(1); } else exit(1); } memset(&qres, 0, sizeof(queres_t)); #endif if (transaction) { if (spocpc_open_transaction(spocp, &qres) != SPOCPC_OK || qres.rescode != SPOCP_SUCCESS) exit(1); } while (fgets(buf, BUFSIZ, fp)) { cp = &buf[strlen(buf) - 1]; while (*cp == '\n' || *cp == '\r' || *cp == ' ') *cp-- = '\0'; if (spocpc_debug) traceLog(LOG_DEBUG,"Got [%s]", buf); if (strncmp(buf, "---", 3) == 0 || strncmp(buf, "+++", 3) == 0 || strncmp(buf, "@@", 2) == 0 || *buf == ' ') continue; s = cp = buf; if (*s == ' ') continue; /* should have path SP [ruleid SP] rule */ /* should do some error checking here ! */ path = ++cp; cp = index(path, ' '); *cp++ = '\0'; if (rid) { /* get ruleid */ ruleid = cp; cp = index(ruleid, ' '); *cp++ = '\0'; } else ruleid = 0; if (spocpc_debug) traceLog(LOG_DEBUG,"path [%s]", path); memset(&qres, 0, sizeof(queres_t)); if (*s == '+') { if (spocpc_debug) traceLog(LOG_DEBUG,"rule [%s]", cp); res = spocpc_str_send_add(spocp, path, cp, 0, 0, &qres); } else if (rid) { /* can't do delete without a ruleid */ if (spocpc_debug) traceLog(LOG_DEBUG,"ruleid [%s]", ruleid); res = spocpc_str_send_delete(spocp, path, ruleid, &qres); } else res = SPOCPC_PARAM_ERROR; if (res == SPOCPC_OK) { if (qres.rescode == SPOCP_SUCCESS) printf("OK\n"); else if (qres.rescode == SPOCP_DENIED) printf("DENIED\n"); else printf("ERROR (%d): %s", qres.rescode, qres.str); } else printf("PROCESS ERROR: %d", res); } if (transaction) { memset(&qres, 0, sizeof(queres_t)); if (spocpc_commit(spocp, &qres) != SPOCPC_OK || qres.rescode != SPOCP_SUCCESS) printf("ERROR commiting"); } memset(&qres, 0, sizeof(queres_t)); spocpc_send_logout(spocp); spocpc_close(spocp); free_spocp(spocp); exit(0); }
int main(int argc, char **argv) { int debug = 0, conftest = 0, nodaemon = 0; int i = 0; unsigned int clilen; struct sockaddr_in cliaddr; struct timeval start, end; char *cnfg = DEF_CNFG; char localhost[MAXNAMLEN + 1], path[MAXNAMLEN + 1]; FILE *pidfp; octet_t oct; ruleset_t *rs; /* * Who am I running as ? */ uname(&myname); /* * spocp_err = 0 ; */ memset(&srv, 0, sizeof(srv_t)); pthread_mutex_init(&(srv.mutex), NULL); pthread_mutex_init(&(srv.mlock), NULL); gethostname(localhost, MAXNAMLEN); #ifdef HAVE_GETDOMAINNAME getdomainname(path, MAXNAMLEN); #else { char *pos; if(pos = strstr(localhost, ".")) strncpy(path, pos+1, MAXNAMLEN); else strcpy(path, ""); } #endif if (0) printf("Domain: %s\n", path); srv.hostname = Strdup(localhost); /* * truncating input strings to reasonable length */ for (i = 0; i < argc; i++) if (strlen(argv[i]) > 512) argv[i][512] = '\0'; while ((i = getopt(argc, argv, "Dhrtf:d:")) != EOF) { switch (i) { case 'D': nodaemon = 1; break; case 'f': cnfg = Strdup(optarg); break; case 'd': debug = atoi(optarg); if (debug < 0) debug = 0; break; case 't': conftest = 1; break; case 'r': srv.readonly = 1; case 'h': default: fprintf(stderr, "Usage: %s [-t] ", argv[0]); fprintf(stderr, "[-f configfile] "); fprintf(stderr, "[-D] [-d debuglevel]\n"); exit(0); } } srv.root = ruleset_new(0); if (srv_init(&srv, cnfg) < 0) exit(1); if (srv.port && srv.uds) { fprintf(stderr, "Sorry are not allowed to listen on both a unix domain socket and a port\n"); exit(1); } if (srv.logfile) spocp_open_log(srv.logfile, debug); else if (debug) spocp_open_log(0, debug); if (srv.name){ localcontext = (char *) Calloc(strlen(srv.name) + strlen("//") + 1, sizeof(char)); /* Flawfinder: ignore */ sprintf(localcontext, "//%s", srv.name); } else { localcontext = (char *) Calloc(strlen(localhost) + strlen("//") + 1, sizeof(char)); /* Flawfinder: ignore */ sprintf(localcontext, "//%s", localhost); } /* * where I put the access rules for access to this server and its * rules */ snprintf(path, MAXNAMLEN, "%s/server", localcontext); oct_assign(&oct, path); if ((rs = ruleset_create(&oct, srv.root)) == 0) exit(1); rs->db = db_new(); /* * access rules for operations */ snprintf(path, MAXNAMLEN, "%s/operation", localcontext); oct_assign(&oct, path); if ((rs = ruleset_create(&oct, srv.root)) == 0) exit(1); rs->db = db_new(); LOG(SPOCP_INFO) { traceLog(LOG_INFO, "Local context: \"%s\"", localcontext); traceLog(LOG_INFO, "initializing backends"); if (srv.root->db) plugin_display(srv.plugin); } if (srv.plugin) { run_plugin_init(&srv); } if ( get_rules( &srv ) != SPOCP_SUCCESS ) exit(1); /*ruleset_tree( srv.root, 0);*/ /* If only testing configuration and rulefile this is as far as I go */ if (conftest) { traceLog(LOG_INFO,"Configuration was OK"); exit(0); } gettimeofday(&start, NULL); if (srv.port || srv.uds) { /* * stdin and stdout will not be used from here on, close to * save file descriptors */ fclose(stdin); fclose(stdout); #ifdef HAVE_SSL /* * ---------------------------------------------------------- */ /* * build our SSL context, whether it will ever be used or not */ /* * mutex'es for openSSL to use */ THREAD_setup(); if (srv.certificateFile && srv.privateKey && srv.caList) { traceLog(LOG_INFO,"Initializing the TLS/SSL environment"); if (!(srv.ctx = tls_init(&srv))) { return FALSE; } } /* * ---------------------------------------------------------- */ #endif #ifdef HAVE_SASL { int r = sasl_server_init(sasl_cb, "spocp"); if (r != SASL_OK) { traceLog( LOG_ERR, "Unable to initialized SASL library: %s", sasl_errstring(r, NULL, NULL)); return FALSE; } } #endif saci_init(); if( nodaemon == 0 ) { #ifdef HAVE_DAEMON if (daemon(1, 1) < 0) { fprintf(stderr, "couldn't go daemon\n"); exit(1); } #else daemon_init("spocp", 0); #endif } if (srv.pidfile) { /* * Write the PID file. */ pidfp = fopen(srv.pidfile, "w"); if (pidfp == (FILE *) 0) { fprintf(stderr, "Couldn't open pidfile \"%s\"\n", srv.pidfile); exit(1); } fprintf(pidfp, "%d\n", (int) getpid()); fclose(pidfp); } if (srv.port) { LOG(SPOCP_INFO) traceLog( LOG_INFO, "Asked to listen on port %d", srv.port); if ((srv.listen_fd = spocp_stream_socket(srv.port)) < 0) exit(1); srv.id = (char *) Malloc(16); sprintf(srv.id, "spocp-%d", srv.port); srv.type = AF_INET; } else { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Asked to listen on unix domain socket"); if ((srv.listen_fd = spocp_unix_domain_socket(srv.uds)) < 0) exit(1); srv.id = (char *) Malloc(7 + strlen(srv.uds)); /* Flawfinder: ignore */ sprintf(srv.id, "spocp-%s", srv.uds); srv.type = AF_UNIX; } xsignal(SIGCHLD, sig_chld); xsignal(SIGPIPE, sig_pipe); xsignal(SIGINT, sig_int); xsignal(SIGTERM, sig_term); xsignal(SIGUSR1, sig_usr1); clilen = sizeof(cliaddr); DEBUG(SPOCP_DSRV) traceLog(LOG_DEBUG,"Creating threads"); /* * returns the pool the threads are picking work from */ srv.work = tpool_init(srv.threads, 64, 1); spocp_srv_run(&srv); } else { conn_t *conn; saci_init(); DEBUG(SPOCP_DSRV) traceLog(LOG_DEBUG,"---->"); LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading STDIN"); /* * If I want to use this I have to do init_server() first * conn = spocp_open_connection( STDIN_FILENO, &srv ) ; */ /* * this is much simpler */ conn = conn_new(); conn_setup(conn, &srv, STDIN_FILENO, "localhost", "127.0.0.1"); LOG(SPOCP_INFO) traceLog(LOG_INFO,"Running server"); spocp_server((void *) conn); gettimeofday(&end, NULL); print_elapsed("query time:", start, end); conn_free( conn ); } srv_free( &srv ); if (cnfg != DEF_CNFG) Free( cnfg ); exit(0); }
spocp_result_t tls_start(conn_t * conn, ruleset_t * rs) { SSL *ssl; SSL_CTX *ctx = (SSL_CTX *) conn->srv->ctx; int maxbits, r, n = 0; char *sid_ctx = "spocp"; SSL_CIPHER *cipher; if (conn->ssl != NULL) { tls_error(SPOCP_WARNING, conn, "STARTTLS received on already encrypted connection"); return SPOCP_STATE_VIOLATION; } if (!(ssl = SSL_new(ctx))) { tls_error(SPOCP_ERR, conn, "Error creating SSL context"); return SPOCP_OPERATIONSERROR; } /* * do these never fail ?? */ SSL_set_session_id_context(ssl, (unsigned char *) sid_ctx, strlen(sid_ctx)); if (SSL_set_fd(ssl, conn->fd) == 0) { traceLog(LOG_ERR,"Couldn't set filedescriptor in SSL"); return SPOCP_OPERATIONSERROR; } n = iobuf_content(conn->in); traceLog(LOG_INFO,"tls_start: %d bytes in input buffer", n); if (n) { traceLog(LOG_INFO,"tls_start: %x%x%x%x", conn->in->r[0], conn->in->r[1], conn->in->r[2], conn->in->r[3]); } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Waiting for client on %d to initiate handshake", conn->fd); /* * waits for the client to initiate the handshake */ { fd_set rset ; int retval ; FD_ZERO( &rset ); FD_SET( conn->fd, &rset ); traceLog(LOG_DEBUG, "Waiting for the client" ) ; retval = select(conn->fd+1,&rset,NULL,NULL,0) ; } if ((r = SSL_accept(ssl)) <= 0) { int se ; if ((se = SSL_get_error(ssl, r)) == SSL_ERROR_WANT_READ) { traceLog(LOG_DEBUG,"Want_read"); } else if (se == SSL_ERROR_SYSCALL) { unsigned long err ; err = ERR_get_error(); if( err == 0L && r == 0 ) { traceLog(LOG_DEBUG,"EOF observed") ; } else traceLog(LOG_ERR,"I/O error occured (%ld/%d)", err, r); } else { traceLog(LOG_ERR,"SSL_get_error: %d", se); tls_error(SPOCP_ERR, conn, "SSL accept error"); SSL_free(ssl); } conn->status = CNST_ACTIVE; return SPOCP_SSL_ERR; } /* * } */ LOG(SPOCP_DEBUG) { traceLog(LOG_DEBUG,"SSL accept done"); traceLog(LOG_DEBUG,"Checking client certificate"); } if (!check_cert_chain(conn, ssl, rs)) { traceLog(LOG_ERR,"Certificate chain check failed"); SSL_free(ssl); conn->status = CNST_ACTIVE; return SPOCP_CERT_ERR; } /* * So the cert is OK and the hostname is in the DN, but do I want to * talk to this guy ?? */ cipher = SSL_get_current_cipher(ssl); conn->cipher = Strdup((char *) SSL_CIPHER_get_name(cipher)); conn->ssl_vers = Strdup(SSL_CIPHER_get_version(cipher)); if (server_access(conn) == 0) { traceLog(LOG_ERR,"Client not allowed access"); SSL_free(ssl); conn->status = CNST_ACTIVE; return SPOCP_CERT_ERR; } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"SSL accept done"); /* * TLS has been set up. Change input/output to read via TLS instead */ conn->readn = ssl_socket_readn; conn->writen = ssl_socket_writen; conn->close = tls_close; conn->ssl = (void *) ssl; conn->tls_ssf = SSL_CIPHER_get_bits(cipher, &maxbits); conn->status = CNST_ACTIVE; return SPOCP_SUCCESS; }
/* * Check that the common name matches the host name */ static int check_cert_chain(conn_t * conn, SSL * ssl, ruleset_t * rs) { X509 *peer; X509_NAME *xn; static char subject[1024]; int r = FALSE, extc; if (SSL_get_verify_result(ssl) != X509_V_OK) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Certificate doesn't verify"); return FALSE; } /* * Check the cert chain. The chain length is automatically checked by * OpenSSL when we set the verify depth in the ctx */ peer = SSL_get_peer_certificate(ssl); if (!peer) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"No peer certificate"); return TRUE; } /* * check subjectaltname */ if ((extc = X509_get_ext_count(peer)) > 0) { int i; for (i = 0; r == FALSE && i < extc; i++) { X509_EXTENSION *ext; const char *extstr; ext = X509_get_ext(peer, i); extstr = OBJ_nid2sn(OBJ_obj2nid (X509_EXTENSION_get_object(ext))); if (strcmp(extstr, "subjectAltName") == 0) { int j; unsigned char *data; STACK_OF(CONF_VALUE) * val; CONF_VALUE *nval; X509V3_EXT_METHOD *meth; if ((meth = X509V3_EXT_get(ext)) == 0) break; data = ext->value->data; val = meth->i2v(meth, meth->d2i(NULL, &data, ext->value->length), NULL); for (j = 0; r == FALSE && i < sk_CONF_VALUE_num(val); j++) { nval = sk_CONF_VALUE_value(val, j); if (strcasecmp(nval->name, "DNS") == 0 && strcasecmp(nval->value, conn->sri. hostname)) { r = TRUE; } } } } } if (r == FALSE) { /* * Check the subject name */ xn = X509_get_subject_name(peer); X509_NAME_get_text_by_NID(xn, NID_commonName, subject, 1024); subject[1023] = '\0'; traceLog(LOG_DEBUG,"\"%s\" = \"%s\" ?", subject, conn->sri.hostname); if (strcasecmp(subject, conn->sri.hostname) == 0) { r = TRUE; } } if (r == TRUE) { conn->subjectDN = X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0); conn->issuerDN = X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0); } X509_free(peer); return r; }