NOEXPORT int add_rand_file(GLOBAL_OPTIONS *global, const char *filename) { int readbytes; int writebytes; struct stat sb; if(stat(filename, &sb)) return 0; /* could not stat() file --> return 0 bytes */ if((readbytes=RAND_load_file(filename, global->random_bytes))) s_log(LOG_DEBUG, "Snagged %d random bytes from %s", readbytes, filename); else s_log(LOG_INFO, "Cannot retrieve any random data from %s", filename); /* write new random data for future seeding if it's a regular file */ if(global->option.rand_write && S_ISREG(sb.st_mode)) { writebytes=RAND_write_file(filename); if(writebytes==-1) s_log(LOG_WARNING, "Failed to write strong random data to %s - " "may be a permissions or seeding problem", filename); else s_log(LOG_DEBUG, "Wrote %d new random bytes to %s", writebytes, filename); } return readbytes; }
static void init_openssl(struct module *module) { unsigned char f_randfile[PATH_MAX]; /* In a nutshell, on OS's without a /dev/urandom, the OpenSSL library * cannot initialize the PRNG and so every attempt to use SSL fails. * It's actually an OpenSSL FAQ, and according to them, it's up to the * application coders to seed the RNG. -- William Yodlowsky */ RAND_file_name(f_randfile, sizeof(f_randfile)); #ifdef HAVE_RAND_EGD if (RAND_egd(f_randfile) < 0) { /* Not an EGD, so read and write to it */ #endif if (RAND_load_file(f_randfile, -1)) RAND_write_file(f_randfile); #ifdef HAVE_RAND_EGD } #endif SSLeay_add_ssl_algorithms(); context = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(context, SSL_OP_ALL); SSL_CTX_set_default_verify_paths(context); socket_SSL_ex_data_idx = SSL_get_ex_new_index(0, NULL, NULL, socket_SSL_ex_data_dup, NULL); }
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; static int seeded = 0; switch (iMsg) { case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); DrawText(hdc, "Seeding the PRNG. Please move the mouse!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } if (RAND_event(iMsg, wParam, lParam) == 1 && seeded == 0) { seeded = 1; if (RAND_write_file(filename) <= 0) MessageBox(hwnd, "Couldn't write random file!", "OpenSSL", MB_OK | MB_ICONERROR); PostQuitMessage(0); } return DefWindowProc(hwnd, iMsg, wParam, lParam); }
void openssl_bioBS_random() { int size; const char *p; unsigned char outs[SHA_DIGEST_LENGTH + 16] = { 0 }; char buf[32], filename[COMM_LEN]; strcpy(buf, "bioBS random"); RAND_add(buf, 32, strlen(buf)); strcpy(buf, "beike2012"); RAND_seed(buf, 32); while (1) { if (RAND_status() == 1) break; else RAND_poll(); } p = RAND_file_name(filename, COMM_LEN); RAND_write_file(p); RAND_load_file(p, MAX1_LEN); RAND_bytes(outs, sizeof(outs)); printf("\nBIO_RANDOM() = "); for (size = 0; size < strlen((char *)&outs); size++) printf("%.02x", outs[size]); printf("\n"); RAND_cleanup(); }
static int add_rand_file(char *filename) { int readbytes; #ifdef WRITE_SEED_DATA int writebytes; #endif if ((readbytes = RAND_load_file(filename, 255))) { Debug((DEBUG_DEBUG, "Got 255 random bytes from %s", filename)); } else { Debug((DEBUG_NOTICE, "Unable to retrieve any random data from %s", filename)); } #ifdef WRITE_SEED_DATA writebytes = RAND_write_file(WRITE_SEED_DATA); if (writebytes == -1) { Debug((DEBUG_ERROR, "Failed to write strong random data to %s - " "may be a permissions or seeding problem", WRITE_SEED_DATA)); } else { Debug((DEBUG_DEBUG, "Wrote %d new random bytes to %s", writebytes, WRITE_SEED_DATA)); } #endif /* WRITE_SEED_DATA */ return readbytes; }
void CryptoDeInitialize() { if (crypto_initialized) { char randfile[CF_BUFSIZE]; snprintf(randfile, CF_BUFSIZE, "%s%crandseed", CFWORKDIR, FILE_SEPARATOR); /* Only write out a seed if the file doesn't exist * and we have enough entropy to do so. If RAND_write_File * returns a bad value, delete the poor seed. */ if (access(randfile, R_OK) && errno == ENOENT && RAND_write_file(randfile) != 1024) { //Log(LOG_LEVEL_VERBOSE, "Could not write randomness to '%s'", randfile); unlink(randfile); /* do not reuse entropy */ } chmod(randfile, 0600); EVP_cleanup(); CleanupOpenSSLThreadLocks(); ERR_free_strings(); crypto_initialized = false; } }
int _randfile( void ) { char randfile[ MAXPATHLEN ]; /* generates a default path for the random seed file */ if ( RAND_file_name( randfile, sizeof( randfile )) == NULL ) { fprintf( stderr, "RAND_file_name: %s\n", ERR_error_string( ERR_get_error(), NULL )); return( -1 ); } /* reads the complete randfile and adds them to the PRNG */ if ( RAND_load_file( randfile, -1 ) <= 0 ) { fprintf( stderr, "RAND_load_file: %s: %s\n", randfile, ERR_error_string( ERR_get_error(), NULL )); return( -1 ); } /* writes a number of random bytes (currently 1024) to randfile */ if ( RAND_write_file( randfile ) < 0 ) { fprintf( stderr, "RAND_write_file: %s: %s\n", randfile, ERR_error_string( ERR_get_error(), NULL )); return( -1 ); } return( 0 ); }
SSL *getSSL(void) { if (!context) { const SSL_METHOD *m; unsigned char f_randfile[PATH_MAX]; const unsigned char *f = (const unsigned char *)RAND_file_name(cast_char f_randfile, sizeof(f_randfile)); if (f && RAND_egd(cast_const_char f)<0) { /* Not an EGD, so read and write to it */ if (RAND_load_file(cast_const_char f_randfile, -1)) RAND_write_file(cast_const_char f_randfile); } SSLeay_add_ssl_algorithms(); m = SSLv23_client_method(); if (!m) return NULL; context = SSL_CTX_new((void *)m); if (!context) return NULL; SSL_CTX_set_options(context, SSL_OP_ALL); SSL_CTX_set_default_verify_paths(context); /* needed for systems without /dev/random, but obviously kills security. */ /*{ unsigned char pool[32768]; int i; int rs; struct timeval tv; EINTRLOOP(rs, gettimeofday(&tv, NULL)); for (i = 0; i < sizeof pool; i++) pool[i] = random() ^ tv.tv_sec ^ tv.tv_usec; RAND_add(pool, sizeof pool, sizeof pool); }*/ } return (SSL_new(context)); }
static int seed_something(void) { #ifndef NO_RANDFILE char buf[1024], seedfile[256]; /* If there is a seed file, load it. But such a file cannot be trusted, so use 0 for the entropy estimate */ if (RAND_file_name(seedfile, sizeof(seedfile))) { int fd; fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); if (fd >= 0) { ssize_t ret; rk_cloexec(fd); ret = read(fd, buf, sizeof(buf)); if (ret > 0) RAND_add(buf, ret, 0.0); close(fd); } else seedfile[0] = '\0'; } else seedfile[0] = '\0'; #endif /* Calling RAND_status() will try to use /dev/urandom if it exists so we do not have to deal with it. */ if (RAND_status() != 1) { #if defined(HAVE_RAND_EGD) krb5_context context; const char *p; #ifndef OPENSSL_NO_EGD /* Try using egd */ if (!krb5_init_context(&context)) { p = krb5_config_get_string(context, NULL, "libdefaults", "egd_socket", NULL); if (p != NULL) RAND_egd_bytes(p, ENTROPY_NEEDED); krb5_free_context(context); } #endif #else /* TODO: Once a Windows CryptoAPI RAND method is defined, we can use that and failover to another method. */ #endif } if (RAND_status() == 1) { #ifndef NO_RANDFILE /* Update the seed file */ if (seedfile[0]) RAND_write_file(seedfile); #endif return 0; } else return -1; }
int seed_prng(char **errstr) { char randfile[512]; time_t t; int prn; int system_prn_max = 1024; /* Most systems have /dev/random or other sources of random numbers that * OpenSSL can use to seed itself. * The only system I know of where we must seed the PRNG is DOS. */ if (!RAND_status()) { if (!RAND_file_name(randfile, 512)) { *errstr = xasprintf(_("no environment variables RANDFILE or HOME, " "or filename of rand file too long")); return TLS_ESEED; } if (RAND_load_file(randfile, -1) < 1) { *errstr = xasprintf(_("%s: input error"), randfile); return TLS_ESEED; } /* Seed in time. I can't think of other "random" things on DOS * systems. */ if ((t = time(NULL)) < 0) { *errstr = xasprintf(_("cannot get system time: %s"), strerror(errno)); return TLS_ESEED; } RAND_seed((unsigned char *)&t, sizeof(time_t)); /* If the RANDFILE + time is not enough, we fall back to the insecure * and stupid method of seeding OpenSSLs PRNG with the systems PRNG. */ if (!RAND_status()) { srand((unsigned int)(t % UINT_MAX)); while (!RAND_status() && system_prn_max > 0) { prn = rand(); RAND_seed(&prn, sizeof(int)); system_prn_max--; } } /* Are we happy now? */ if (!RAND_status()) { *errstr = xasprintf(_("random file + time + pseudo randomness is " "not enough, giving up")); return TLS_ESEED; } /* Save a rand file for later usage. We ignore errors here as we can't * do anything about them. */ (void)RAND_write_file(randfile); } return TLS_EOK; }
/* * call-seq: * write_random_file(filename) -> true * */ static VALUE ossl_rand_write_file(VALUE self, VALUE filename) { SafeStringValue(filename); if (RAND_write_file(RSTRING_PTR(filename)) == -1) { ossl_raise(eRandomError, NULL); } return Qtrue; }
void csprng_engine::save_state (std::string const& file) { if (!file.empty()) { std::lock_guard<std::mutex> lock (mutex_); RAND_write_file (file.c_str ()); } }
/* Free the SSL CTX, clean up the mess */ void ssl_cleanup() { if (ssl_ctx) { SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; } if (tls_randfile) RAND_write_file(tls_randfile); ERR_free_strings(); }
static void save_seed(void) { assert(*g_seed_file); if (!g_seeded) return; /* so we won't pollute the seed file*/ RAND_write_file(g_seed_file); }
/*** save rand seed to file @function rand_write @tparam[opt=nil] string file path to save seed, default openssl management @treturn bool result */ static int openssl_random_write(lua_State *L) { const char *file = luaL_optstring(L, 1, NULL); char buffer[MAX_PATH]; if (file == NULL && (file = RAND_file_name(buffer, sizeof buffer)) == NULL) return openssl_pushresult(L, 0); RAND_write_file(file); return openssl_pushresult(L, 1); }
void crypto_deinit(void) { char rnd_file[256]; if (randfile_loaded) { RAND_file_name(rnd_file, sizeof(rnd_file)); if (rnd_file[0]) RAND_write_file(rnd_file); } crypto_deinit_threading(); }
static int rand_write(lua_State *L) { const char *name = luaL_optstring(L, 1, 0); char tmp[256]; int n; if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) return crypto_error(L); n = RAND_write_file(name); if (n == 0) return crypto_error(L); lua_pushnumber(L, n); return 1; }
static int tlso_seed_PRNG( const char *randfile ) { #ifndef URANDOM_DEVICE /* no /dev/urandom (or equiv) */ long total=0; char buffer[MAXPATHLEN]; if (randfile == NULL) { /* The seed file is $RANDFILE if defined, otherwise $HOME/.rnd. * If $HOME is not set or buffer too small to hold the pathname, * an error occurs. - From RAND_file_name() man page. * The fact is that when $HOME is NULL, .rnd is used. */ randfile = RAND_file_name( buffer, sizeof( buffer ) ); } else if (RAND_egd(randfile) > 0) { /* EGD socket */ return 0; } if (randfile == NULL) { Debug( LDAP_DEBUG_ANY, "TLS: Use configuration file or $RANDFILE to define seed PRNG\n", 0, 0, 0); return -1; } total = RAND_load_file(randfile, -1); if (RAND_status() == 0) { Debug( LDAP_DEBUG_ANY, "TLS: PRNG not been seeded with enough data\n", 0, 0, 0); return -1; } /* assume if there was enough bits to seed that it's okay * to write derived bits to the file */ RAND_write_file(randfile); #endif return 0; }
void SSLConnection::init () { did_init = false; buffer_t path; buffer_init(&path); buffer_grow(&path,_POSIX_PATH_MAX+1); if (!HAVE_ENTROPY ()) { /* load entropy from files */ if (SSLEntropyFile) add_entropy (SSLEntropyFile); add_entropy (RAND_file_name (path.str,path.size)); /* load entropy from egd sockets */ #ifdef HAVE_RAND_EGD add_entropy (getenv ("EGDSOCKET")); buffer_shrink(&path,0); buffer_add_str(&path,NONULL(Homedir),-1); buffer_add_str(&path,"/.entropy",9); add_entropy (path.str); add_entropy ("/tmp/entropy"); #endif /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file (RAND_file_name (path.str,path.size)); if (!HAVE_ENTROPY ()) { buffer_t msg; buffer_init(&msg); buffer_add_str(&msg,_("Failed to find enough entropy on your system"),-1); displayError.emit(&msg); buffer_free(&msg); buffer_free(&path); return; } } /* * I don't think you can do this just before reading the error. * The call itself might clobber the last SSL error. */ SSL_load_error_strings (); SSL_library_init (); did_init = true; buffer_free(&path); }
/** * ssl_init - Initialise the SSL library * @retval 0 Success * @retval -1 Error * * OpenSSL library needs to be fed with sufficient entropy. On systems with * /dev/urandom, this is done transparently by the library itself, on other * systems we need to fill the entropy pool ourselves. * * Even though only OpenSSL 0.9.5 and later will complain about the lack of * entropy, we try to our best and fill the pool with older versions also. * (That's the reason for the ugly ifdefs and macros, otherwise I could have * simply ifdef'd the whole ssl_init function) */ static int ssl_init(void) { static bool init_complete = false; if (init_complete) return 0; if (!HAVE_ENTROPY()) { /* load entropy from files */ char path[PATH_MAX]; add_entropy(C_EntropyFile); add_entropy(RAND_file_name(path, sizeof(path))); /* load entropy from egd sockets */ #ifdef HAVE_RAND_EGD add_entropy(mutt_str_getenv("EGDSOCKET")); snprintf(path, sizeof(path), "%s/.entropy", NONULL(HomeDir)); add_entropy(path); add_entropy("/tmp/entropy"); #endif /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof(path))); mutt_clear_error(); if (!HAVE_ENTROPY()) { mutt_error(_("Failed to find enough entropy on your system")); return -1; } } /* OpenSSL performs automatic initialization as of 1.1. * However LibreSSL does not (as of 2.8.3). */ #if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || \ (defined(LIBRESSL_VERSION_NUMBER)) /* I don't think you can do this just before reading the error. The call * itself might clobber the last SSL error. */ SSL_load_error_strings(); SSL_library_init(); #endif init_complete = true; return 0; }
int app_RAND_write_file(const char *file) { char buffer[200]; if (egdsocket || !seeded) /* * If we did not manage to read the seed file, we should not write a * low-entropy seed file back -- it would suppress a crucial warning * the next time we want to use it. */ return 0; if (file == NULL) file = RAND_file_name(buffer, sizeof buffer); if (file == NULL || !RAND_write_file(file)) { BIO_printf(bio_err, "unable to write 'random state'\n"); return 0; } return 1; }
/* * OpenSSL library needs to be fed with sufficient entropy. On systems * with /dev/urandom, this is done transparently by the library itself, * on other systems we need to fill the entropy pool ourselves. * * Even though only OpenSSL 0.9.5 and later will complain about the * lack of entropy, we try to our best and fill the pool with older * versions also. (That's the reason for the ugly #ifdefs and macros, * otherwise I could have simply #ifdef'd the whole ssl_init funcion) */ static int ssl_init (void) { char path[_POSIX_PATH_MAX]; static unsigned char init_complete = 0; if (init_complete) return 0; if (! HAVE_ENTROPY()) { /* load entropy from files */ add_entropy (SslEntropyFile); add_entropy (RAND_file_name (path, sizeof (path))); /* load entropy from egd sockets */ #ifdef HAVE_RAND_EGD add_entropy (getenv ("EGDSOCKET")); snprintf (path, sizeof(path), "%s/.entropy", NONULL(Homedir)); add_entropy (path); add_entropy ("/tmp/entropy"); #endif /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file (RAND_file_name (path, sizeof (path))); mutt_clear_error (); if (! HAVE_ENTROPY()) { mutt_error (_("Failed to find enough entropy on your system")); mutt_sleep (2); return -1; } } /* I don't think you can do this just before reading the error. The call * itself might clobber the last SSL error. */ SSL_load_error_strings(); SSL_library_init(); init_complete = 1; return 0; }
static int add_rand_file(char *filename) { int readbytes; int writebytes; struct stat sb; if(stat(filename, &sb)) return 0; if((readbytes=RAND_load_file(filename, options.random_bytes))) log(LOG_DEBUG, "Snagged %d random bytes from %s", readbytes, filename); else log(LOG_INFO, "Unable to retrieve any random data from %s", filename); /* Write new random data for future seeding if it's a regular file */ if(options.option.rand_write && (sb.st_mode & S_IFREG)){ writebytes = RAND_write_file(filename); if(writebytes==-1) log(LOG_WARNING, "Failed to write strong random data to %s - " "may be a permissions or seeding problem", filename); else log(LOG_DEBUG, "Wrote %d new random bytes to %s", writebytes, filename); } return readbytes; }
SSL *getSSL(void) { if (!context) { const SSL_METHOD *m; unsigned char *os_pool; int os_pool_size; #if defined(HAVE_RAND_EGD) && defined(HAVE_RAND_FILE_NAME) && defined(HAVE_RAND_LOAD_FILE) && defined(HAVE_RAND_WRITE_FILE) { unsigned char f_randfile[PATH_MAX]; const unsigned char *f = (const unsigned char *)RAND_file_name(cast_char f_randfile, sizeof(f_randfile)); if (f && RAND_egd(cast_const_char f) < 0) { /* Not an EGD, so read and write to it */ if (RAND_load_file(cast_const_char f_randfile, -1)) RAND_write_file(cast_const_char f_randfile); } } #endif #if defined(HAVE_RAND_ADD) os_seed_random(&os_pool, &os_pool_size); if (os_pool_size) RAND_add(os_pool, os_pool_size, os_pool_size); mem_free(os_pool); #endif SSLeay_add_ssl_algorithms(); m = SSLv23_client_method(); if (!m) return NULL; context = SSL_CTX_new((void *)m); if (!context) return NULL; SSL_CTX_set_options(context, SSL_OP_ALL); if (ssl_set_private_paths()) SSL_CTX_set_default_verify_paths(context); SSL_CTX_set_default_passwd_cb(context, ssl_password_callback); } return SSL_new(context); }
static int rand_write(lua_State *L) { const char *name = luaL_optstring(L, 1, NULL); #if CRYPTO_OPENSSL char tmp[256]; int n; if (!name && !(name = RAND_file_name(tmp, sizeof tmp))) return crypto_error(L); n = RAND_write_file(name); if (n == 0) return crypto_error(L); lua_pushnumber(L, n); #elif CRYPTO_GCRYPT /* this is a BUG() in gcrypt. not sure if it refers to the lib or to the caller, but it does not work (to set twice this file) */ /* if (name != NULL) gcry_control(GCRYCTL_SET_RANDOM_SEED_FILE,name); */ gcry_control(GCRYCTL_UPDATE_RANDOM_SEED_FILE); lua_pushnumber(L, 0.0); #endif return 1; }
int main( int argc, char *argv[] ) { char *fn = "main()"; char f_randfile[ PATH_MAX ]; int listensd; /* socket descriptor we'll bind to */ int clientsd; /* incoming socket descriptor */ int addrlen; struct sockaddr_in srvaddr; struct sockaddr_in cliaddr; pthread_t ThreadId; /* thread id of each incoming conn */ pthread_t RecycleThread; /* used just for the recycle thread */ pthread_attr_t attr; /* generic thread attribute struct */ int rc, i, fd; unsigned int ui; pid_t pid; /* used just for a fork call */ struct linger lingerstruct; /* for the socket reuse stuff */ int flag; /* for the socket reuse stuff */ ICC_Struct *ICC_tptr; extern char *optarg; extern int optind; char ConfigFile[ MAXPATHLEN ]; /* path to our config file */ #ifdef HAVE_LIBWRAP struct request_info r; /* request struct for libwrap */ #endif flag = 1; ConfigFile[0] = '\0'; /* * Ignore signals we don't want to die from but we don't care enough * about to catch. */ signal( SIGPIPE, SIG_IGN ); signal( SIGHUP, SIG_IGN ); while (( i = getopt( argc, argv, "f:h" ) ) != EOF ) { switch( i ) { case 'f': /* user specified a config filename */ strncpy( ConfigFile, optarg, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using configuration file '%s'", fn, ConfigFile ); break; case 'h': Usage(); exit( 0 ); case '?': Usage(); exit( 1 ); } } /* * Make sure we know which config file to use and then set our config * options. */ if ( ! ConfigFile[0] ) { strncpy( ConfigFile, DEFAULT_CONFIG_FILE, sizeof ConfigFile -1 ); ConfigFile[ sizeof ConfigFile - 1 ] = '\0'; syslog( LOG_INFO, "%s: Using default configuration file '%s'.", fn, ConfigFile ); } SetConfigOptions( ConfigFile ); SetLogOptions(); /* * Just for logging purposes, are we doing SELECT caching or not? */ if ( PC_Struct.enable_select_cache ) syslog( LOG_INFO, "%s: SELECT caching is enabled", fn ); else syslog( LOG_INFO, "%s: SELECT caching is disabled", fn ); #ifdef HAVE_LIBWRAP /* * Set our tcpd service name */ if (service = strrchr(argv[0], '/')) service++; else service = argv[0]; #endif /* * Initialize some stuff. */ rc = pthread_mutex_init(&mp, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing main mutex. Exiting.", fn, rc ); exit( 1 ); } rc = pthread_mutex_init(&trace, NULL); if ( rc ) { syslog(LOG_ERR, "%s: pthread_mutex_init() returned error [%d] initializing trace mutex. Exiting.", fn, rc ); exit( 1 ); } TraceUser[0] = '\0'; syslog( LOG_INFO, "%s: Allocating %d IMAP connection structures.", fn, PC_Struct.cache_size ); ICC_free = (ICC_Struct *)malloc( ( sizeof ( ICC_Struct ) ) * PC_Struct.cache_size ); if ( ! ICC_free ) { syslog(LOG_ERR, "%s: malloc() failed to allocate [%d] IMAPConnectionContext structures: %s", fn, PC_Struct.cache_size, strerror( errno ) ); exit( 1 ); } memset( ICC_free, 0, sizeof ( ICC_Struct ) * PC_Struct.cache_size ); ICC_tptr = ICC_free; /* * Bug fixed by Gary Mills <*****@*****.**>. I was pre-incrementing * ICC_tptr and then assigning. I guess gcc evaluates the expression * incorrectly, since I never had a problem with this. Gary had the * problem with cc, so it's fixed here. */ for ( ui = 0; ui < PC_Struct.cache_size - 1; ui++ ) { ICC_tptr->next = ICC_tptr + 1; ICC_tptr++; } memset( ICC_HashTable, 0, sizeof ICC_HashTable ); ServerInit(); /* detach from our parent if necessary */ if (! (getppid() == 1) && ( ! PC_Struct.foreground_mode ) ) { syslog( LOG_INFO, "%s: Configured to run in background mode.", fn ); if ( (pid = fork()) < 0) { syslog(LOG_ERR, "%s: initial call to fork() failed: %s", fn, strerror(errno)); exit( 1 ); } else if ( pid > 0) { exit( 0 ); } if (setsid() == -1) { syslog(LOG_WARNING, "%s: setsid() failed: %s", fn, strerror(errno)); } if ( (pid = fork()) < 0) { syslog(LOG_ERR, "%s: secondary call to fork() failed: %s", fn, strerror(errno)); exit( 1 ); } else if ( pid > 0) { exit( 0 ); } } else { syslog( LOG_INFO, "%s: Configured to run in foreground mode.", fn ); } SetBannerAndCapability(); if ( PC_Struct.login_disabled || PC_Struct.force_tls ) { syslog( LOG_INFO, "%s: Enabling STARTTLS.", fn ); #if HAVE_LIBSSL if ( PC_Struct.support_starttls ) { /* Initialize SSL_CTX */ SSL_library_init(); /* Need to seed PRNG, too! */ if ( RAND_egd( ( RAND_file_name( f_randfile, sizeof( f_randfile ) ) == f_randfile ) ? f_randfile : "/.rnd" ) ) { /* Not an EGD, so read and write it. */ if ( RAND_load_file( f_randfile, -1 ) ) RAND_write_file( f_randfile ); } SSL_load_error_strings(); tls_ctx = SSL_CTX_new( TLSv1_client_method() ); if ( tls_ctx == NULL ) { syslog(LOG_ERR, "%s: Failed to create new SSL_CTX. Exiting.", fn); exit( 1 ); } /* Work around all known bugs */ SSL_CTX_set_options( tls_ctx, SSL_OP_ALL ); if ( ! SSL_CTX_load_verify_locations( tls_ctx, PC_Struct.tls_ca_file, PC_Struct.tls_ca_path ) || ! SSL_CTX_set_default_verify_paths( tls_ctx ) ) { syslog(LOG_ERR, "%s: Failed to load CA data. Exiting.", fn); exit( 1 ); } if ( ! set_cert_stuff( tls_ctx, PC_Struct.tls_cert_file, PC_Struct.tls_key_file ) ) { syslog(LOG_ERR, "%s: Failed to load cert/key data. Exiting.", fn); exit( 1 ); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_NONE, verify_callback); } else #endif /* HAVE_LIBSSL */ { /* We're screwed! We won't be able to login without SASL */ syslog(LOG_ERR, "%s: IMAP server has LOGINDISABLED and we can't do STARTTLS. Exiting.", fn); exit( 1 ); } } memset( (char *) &srvaddr, 0, sizeof srvaddr ); srvaddr.sin_family = PF_INET; if ( !PC_Struct.listen_addr ) { srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); } else { srvaddr.sin_addr.s_addr = inet_addr( PC_Struct.listen_addr ); if ( srvaddr.sin_addr.s_addr == -1 ) { syslog( LOG_ERR, "%s: bad bind address: '%s' specified in config file. Exiting.", fn, PC_Struct.listen_addr ); exit( 1 ); } } syslog(LOG_INFO, "%s: Binding to tcp %s:%d", fn, PC_Struct.listen_addr ? PC_Struct.listen_addr : "*", PC_Struct.listen_port ); srvaddr.sin_port = htons(PC_Struct.listen_port); listensd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if ( listensd == -1 ) { syslog(LOG_ERR, "%s: socket() failed: %s", fn, strerror(errno)); exit( 1 ); } setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag)); lingerstruct.l_onoff = 1; lingerstruct.l_linger = 5; setsockopt(listensd, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct)); if ( PC_Struct.send_tcp_keepalives ) { lingerstruct.l_onoff = 1; syslog( LOG_INFO, "%s: Enabling SO_KEEPALIVE.", fn ); setsockopt( listensd, SOL_SOCKET, SO_KEEPALIVE, (void *)&lingerstruct.l_onoff, sizeof lingerstruct.l_onoff ); } if ( bind(listensd, (struct sockaddr *)&srvaddr, sizeof( srvaddr ) ) < 0 ) { syslog(LOG_ERR, "%s: bind() failed: %s", fn, strerror(errno) ); exit( 1 ); } /* * Create and mmap() our stat file while we're still root. Since it's * configurable, we want to make sure we do this as root so there's the * greatest possibility that we'll have permission to write where we * need to. */ syslog( LOG_INFO, "%s: Using global statistics file '%s'", fn, PC_Struct.stat_filename ); fd = open( PC_Struct.stat_filename, O_RDWR | O_CREAT, S_IREAD | S_IWRITE ); if ( fd == -1 ) { syslog(LOG_ERR, "%s: open() failed for '%s': %s -- Exiting.", fn, PC_Struct.stat_filename, strerror( errno ) ); exit( 1 ); } if ( ( ftruncate( fd, sizeof( IMAPCounter_Struct ) ) ) == -1 ) { syslog(LOG_ERR, "%s: ftruncate() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } IMAPCount = ( IMAPCounter_Struct *)mmap( 0, sizeof( IMAPCounter_Struct ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if ( IMAPCount == MAP_FAILED ) { syslog(LOG_ERR, "%s: mmap() failed: %s -- Exiting.", fn, strerror( errno ) ); exit( 1 ); } memset( IMAPCount, 0, sizeof( IMAPCounter_Struct ) ); IMAPCount->StartTime = time( 0 ); IMAPCount->CountTime = time( 0 ); if ( BecomeNonRoot() ) exit( 1 ); /* some misc thread setup */ rc = pthread_attr_init( &attr ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_init() failed: [%d]\n", fn, rc); exit( 1 ); } rc = pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if ( rc ) { syslog(LOG_ERR, "%s: pthread_attr_setdetachstate() failed: [%d]\n", fn, rc); exit( 1 ); } /* launch a recycle thread before we loop */ pthread_create( &RecycleThread, &attr, (void *)ICC_Recycle_Loop, NULL ); syslog(LOG_INFO, "%s: Launched ICC recycle thread with id %d", fn, RecycleThread ); /* * Now start listening and accepting connections. */ if ( listen(listensd, MAX_CONN_BACKLOG) < 0) { syslog( LOG_ERR, "%s: listen() failed: %s -- Exiting", fn, strerror(errno)); exit( 1 ); } syslog( LOG_INFO, "%s: Normal server startup.", fn ); /* * Main server loop */ for ( ;; ) { /* * Bug fixed by Gary Mills <*****@*****.**>. I forgot * to initialize addrlen. */ addrlen = sizeof cliaddr; clientsd = accept( listensd, (struct sockaddr *)&cliaddr, &addrlen ); if ( clientsd == -1 ) { syslog(LOG_WARNING, "%s: accept() failed: %s -- retrying", fn, strerror(errno)); sleep( 1 ); continue; } #ifdef HAVE_LIBWRAP request_init(&r, RQ_DAEMON, service, 0); request_set(&r, RQ_FILE, clientsd, 0); sock_host(&r); if (!hosts_access(&r)) { shutdown(clientsd, SHUT_RDWR); close(clientsd); syslog(deny_severity, "refused connection from %s", eval_client(&r)); continue; } #endif IMAPCount->TotalClientConnectionsAccepted++; IMAPCount->CurrentClientConnections++; if ( IMAPCount->CurrentClientConnections > IMAPCount->PeakClientConnections ) IMAPCount->PeakClientConnections = IMAPCount->CurrentClientConnections; pthread_create( &ThreadId, &attr, (void *)HandleRequest, (void *)clientsd ); } }
static void KeepKeyPromises(void) { unsigned long err; RSA *pair; FILE *fp; struct stat statbuf; int fd; static char *passphrase = "Cfengine passphrase"; const EVP_CIPHER *cipher; char vbuff[CF_BUFSIZE]; NewScope("common"); cipher = EVP_des_ede3_cbc(); if (cfstat(CFPUBKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPUBKEYFILE); return; } if (cfstat(CFPRIVKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPRIVKEYFILE); return; } printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); pair = RSA_generate_key(2048, 35, NULL, NULL); if (pair == NULL) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to generate key: %s\n", ERR_reason_error_string(err)); return; } if (DEBUG) { RSA_print_fp(stdout, pair, 0); } fd = open(CFPRIVKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Open %s failed: %s.", CFPRIVKEYFILE, strerror(errno)); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Couldn't open private key %s.", CFPRIVKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing private key to %s\n", CFPRIVKEYFILE); if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL)) { err = ERR_get_error(); CfOut(cf_error, "", "Couldn't write private key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); fd = open(CFPUBKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Unable to open public key %s.", CFPUBKEYFILE); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Open %s failed.", CFPUBKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing public key to %s\n", CFPUBKEYFILE); if (!PEM_write_RSAPublicKey(fp, pair)) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to write public key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR); RAND_write_file(vbuff); cf_chmod(vbuff, 0644); }
static void setup_ssl(tcptest_t *item) { static int ssl_init_complete = 0; struct servent *sp; char portinfo[100]; X509 *peercert; char *certcn, *certstart, *certend; int err; strbuffer_t *sslinfo; char msglin[2048]; item->sslrunning = 1; if (!ssl_init_complete) { /* Setup entropy */ if (RAND_status() != 1) { char path[PATH_MAX]; /* Path for the random file */ /* load entropy from files */ RAND_load_file(RAND_file_name(path, sizeof (path)), -1); /* load entropy from egd sockets */ RAND_egd("/var/run/egd-pool"); RAND_egd("/dev/egd-pool"); RAND_egd("/etc/egd-pool"); RAND_egd("/var/spool/prngd/pool"); /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof (path))); if (RAND_status() != 1) { errprintf("Failed to find enough entropy on your system"); item->errcode = CONTEST_ESSL; return; } } SSL_load_error_strings(); SSL_library_init(); ssl_init_complete = 1; } if (item->sslctx == NULL) { switch (item->ssloptions->sslversion) { case SSLVERSION_V2: item->sslctx = SSL_CTX_new(SSLv2_client_method()); break; case SSLVERSION_V3: item->sslctx = SSL_CTX_new(SSLv3_client_method()); break; case SSLVERSION_TLS1: item->sslctx = SSL_CTX_new(TLSv1_client_method()); break; default: item->sslctx = SSL_CTX_new(SSLv23_client_method()); break; } if (!item->sslctx) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot create SSL context - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } /* Workaround SSL bugs */ SSL_CTX_set_options(item->sslctx, SSL_OP_ALL); SSL_CTX_set_quiet_shutdown(item->sslctx, 1); /* Limit set of ciphers, if user wants to */ if (item->ssloptions->cipherlist) SSL_CTX_set_cipher_list(item->sslctx, item->ssloptions->cipherlist); if (item->ssloptions->clientcert) { int status; char certfn[PATH_MAX]; SSL_CTX_set_default_passwd_cb(item->sslctx, cert_password_cb); SSL_CTX_set_default_passwd_cb_userdata(item->sslctx, item); sprintf(certfn, "%s/certs/%s", xgetenv("XYMONHOME"), item->ssloptions->clientcert); status = SSL_CTX_use_certificate_chain_file(item->sslctx, certfn); if (status == 1) { status = SSL_CTX_use_PrivateKey_file(item->sslctx, certfn, SSL_FILETYPE_PEM); } if (status != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot load SSL client certificate/key %s: %s\n", item->ssloptions->clientcert, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } } if (item->ssldata == NULL) { item->ssldata = SSL_new(item->sslctx); if (!item->ssldata) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("SSL_new failed - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } /* Verify that the client certificate is working */ if (item->ssloptions->clientcert) { X509 *x509; x509 = SSL_get_certificate(item->ssldata); if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(item->ssldata)); EVP_PKEY_free(pktmp); } if (!SSL_CTX_check_private_key(item->sslctx)) { errprintf("Private/public key mismatch for certificate %s\n", item->ssloptions->clientcert); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } /* SSL setup is done. Now attach the socket FD to the SSL protocol handler */ if (SSL_set_fd(item->ssldata, item->fd) != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Could not initiate SSL on connection - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } } sp = getservbyport(item->addr.sin_port, "tcp"); if (sp) { sprintf(portinfo, "%s (%d/tcp)", sp->s_name, item->addr.sin_port); } else { sprintf(portinfo, "%d/tcp", item->addr.sin_port); } if ((err = SSL_connect(item->ssldata)) != 1) { char sslerrmsg[256]; switch (SSL_get_error (item->ssldata, err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: item->sslrunning = SSLSETUP_PENDING; break; case SSL_ERROR_SYSCALL: ERR_error_string(ERR_get_error(), sslerrmsg); /* Filter out the bogus SSL error */ if (strstr(sslerrmsg, "error:00000000:") == NULL) { errprintf("IO error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); } item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; case SSL_ERROR_SSL: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unspecified SSL error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; default: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unknown error %d in SSL_connect to %s on host %s: %s\n", err, portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; } return; } /* If we get this far, the SSL handshake has completed. So grab the certificate */ peercert = SSL_get_peer_certificate(item->ssldata); if (!peercert) { errprintf("Cannot get peer certificate for %s on host %s\n", portinfo, inet_ntoa(item->addr.sin_addr)); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); return; } sslinfo = newstrbuffer(0); certcn = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0); certstart = strdup(xymon_ASN1_UTCTIME(X509_get_notBefore(peercert))); certend = strdup(xymon_ASN1_UTCTIME(X509_get_notAfter(peercert))); snprintf(msglin, sizeof(msglin), "Server certificate:\n\tsubject:%s\n\tstart date: %s\n\texpire date:%s\n", certcn, certstart, certend); addtobuffer(sslinfo, msglin); item->certsubject = strdup(certcn); item->certexpires = sslcert_expiretime(certend); xfree(certcn); xfree(certstart); xfree(certend); X509_free(peercert); /* We list the available ciphers in the SSL cert data */ { int i; STACK_OF(SSL_CIPHER) *sk; addtobuffer(sslinfo, "\nAvailable ciphers:\n"); sk = SSL_get_ciphers(item->ssldata); for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { int b1, b2; char *cph; b1 = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(sk,i), &b2); cph = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk,i)); snprintf(msglin, sizeof(msglin), "Cipher %d: %s (%d bits)\n", i, cph, b1); addtobuffer(sslinfo, msglin); if ((item->mincipherbits == 0) || (b1 < item->mincipherbits)) item->mincipherbits = b1; } } item->certinfo = grabstrbuffer(sslinfo); }
int main(int argc, char **argv){ int result=OK; int x; char buffer[MAX_INPUT_BUFFER]; char *env_string=NULL; #ifdef HAVE_SSL DH *dh; char seedfile[FILENAME_MAX]; int i,c; #endif /* set some environment variables */ asprintf(&env_string,"NRPE_MULTILINESUPPORT=1"); putenv(env_string); asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION); putenv(env_string); /* process command-line args */ result=process_arguments(argc,argv); if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ printf("\n"); printf("NRPE - Nagios Remote Plugin Executor\n"); printf("Copyright (c) 1999-2008 Ethan Galstad ([email protected])\n"); printf("Version: %s\n",PROGRAM_VERSION); printf("Last Modified: %s\n",MODIFICATION_DATE); printf("License: GPL v2 with exemptions (-l for more info)\n"); #ifdef HAVE_SSL printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); #endif #ifdef HAVE_LIBWRAP printf("TCP Wrappers Available\n"); #endif printf("\n"); #ifdef ENABLE_COMMAND_ARGUMENTS printf("***************************************************************\n"); printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n"); printf("** Read the NRPE SECURITY file for more information **\n"); printf("***************************************************************\n"); printf("\n"); #endif #ifndef HAVE_LIBWRAP printf("***************************************************************\n"); printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n"); printf("** Read the NRPE SECURITY file for more information **\n"); printf("***************************************************************\n"); printf("\n"); #endif } if(show_license==TRUE) display_license(); else if(result!=OK || show_help==TRUE){ printf("Usage: nrpe [-n] -c <config_file> <mode>\n"); printf("\n"); printf("Options:\n"); printf(" -n = Do not use SSL\n"); printf(" <config_file> = Name of config file to use\n"); printf(" <mode> = One of the following two operating modes:\n"); printf(" -i = Run as a service under inetd or xinetd\n"); printf(" -d = Run as a standalone daemon\n"); printf("\n"); printf("Notes:\n"); printf("This program is designed to process requests from the check_nrpe\n"); printf("plugin on the host(s) running Nagios. It can run as a service\n"); printf("under inetd or xinetd (read the docs for info on this), or as a\n"); printf("standalone daemon. Once a request is received from an authorized\n"); printf("host, NRPE will execute the command/plugin (as defined in the\n"); printf("config file) and return the plugin output and return code to the\n"); printf("check_nrpe plugin.\n"); printf("\n"); } if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) exit(STATE_UNKNOWN); /* open a connection to the syslog facility */ /* facility name may be overridden later */ get_log_facility(NRPE_LOG_FACILITY); openlog("nrpe",LOG_PID,log_facility); /* make sure the config file uses an absolute path */ if(config_file[0]!='/'){ /* save the name of the config file */ strncpy(buffer,config_file,sizeof(buffer)); buffer[sizeof(buffer)-1]='\x0'; /* get absolute path of current working directory */ strcpy(config_file,""); getcwd(config_file,sizeof(config_file)); /* append a forward slash */ strncat(config_file,"/",sizeof(config_file)-2); config_file[sizeof(config_file)-1]='\x0'; /* append the config file to the path */ strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1); config_file[sizeof(config_file)-1]='\x0'; } /* read the config file */ result=read_config_file(config_file); /* exit if there are errors... */ if(result==ERROR){ syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file); return STATE_CRITICAL; } /* generate the CRC 32 table */ generate_crc32_table(); /* initialize macros */ for(x=0;x<MAX_COMMAND_ARGUMENTS;x++) macro_argv[x]=NULL; #ifdef HAVE_SSL /* initialize SSL */ if(use_ssl==TRUE){ SSL_library_init(); SSLeay_add_ssl_algorithms(); meth=SSLv23_server_method(); SSL_load_error_strings(); /* use week random seed if necessary */ if(allow_weak_random_seed && (RAND_status()==0)){ if(RAND_file_name(seedfile,sizeof(seedfile)-1)) if(RAND_load_file(seedfile,-1)) RAND_write_file(seedfile); if(RAND_status()==0){ syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged"); srand(time(NULL)); for(i=0;i<500 && RAND_status()==0;i++){ for(c=0;c<sizeof(seedfile);c+=sizeof(int)){ *((int *)(seedfile+c))=rand(); } RAND_seed(seedfile,sizeof(seedfile)); } } } if((ctx=SSL_CTX_new(meth))==NULL){ syslog(LOG_ERR,"Error: could not create SSL context.\n"); exit(STATE_CRITICAL); } /* ADDED 01/19/2004 */ /* use only TLSv1 protocol */ SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* use anonymous DH ciphers */ SSL_CTX_set_cipher_list(ctx,"ADH"); dh=get_dh512(); SSL_CTX_set_tmp_dh(ctx,dh); DH_free(dh); if(debug==TRUE) syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted."); } else{ if(debug==TRUE) syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED."); } #endif /* if we're running under inetd... */ if(use_inetd==TRUE){ /* make sure we're not root */ check_privileges(); /* redirect STDERR to /dev/null */ close(2); open("/dev/null",O_WRONLY); /* handle the connection */ handle_connection(0); } /* else daemonize and start listening for requests... */ else if(fork()==0){ /* we're a daemon - set up a new process group */ setsid(); /* close standard file descriptors */ close(0); close(1); close(2); /* redirect standard descriptors to /dev/null */ open("/dev/null",O_RDONLY); open("/dev/null",O_WRONLY); open("/dev/null",O_WRONLY); chdir("/"); /*umask(0);*/ /* handle signals */ signal(SIGQUIT,sighandler); signal(SIGTERM,sighandler); signal(SIGHUP,sighandler); /* log info to syslog facility */ syslog(LOG_NOTICE,"Starting up daemon"); /* write pid file */ if(write_pid_file()==ERROR) return STATE_CRITICAL; /* drop privileges */ drop_privileges(nrpe_user,nrpe_group); /* make sure we're not root */ check_privileges(); do{ /* reset flags */ sigrestart=FALSE; sigshutdown=FALSE; /* wait for connections */ wait_for_connections(); /* free all memory we allocated */ free_memory(); if(sigrestart==TRUE){ /* read the config file */ result=read_config_file(config_file); /* exit if there are errors... */ if(result==ERROR){ syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file); return STATE_CRITICAL; } } }while(sigrestart==TRUE && sigshutdown==FALSE); /* remove pid file */ remove_pid_file(); syslog(LOG_NOTICE,"Daemon shutdown\n"); } #ifdef HAVE_SSL if(use_ssl==TRUE) SSL_CTX_free(ctx); #endif /* We are now running in daemon mode, or the connection handed over by inetd has been completed, so the parent process exits */ return STATE_OK; }
SSL_CTX * tls_init(srv_t * srv) { char path[_POSIX_PATH_MAX]; SSL_CTX *ctx; int r; char errorstr[1024]; unsigned long e; SSL_library_init(); SSL_load_error_strings(); /* basic set up */ OpenSSL_add_ssl_algorithms(); /* * Create a TLS context */ if (!(ctx = SSL_CTX_new(SSLv23_method()))) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error allocation SSL_CTX"); return 0; } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Do we have enough randomness ??"); if (!RAND_status()) { /* * load entropy from files */ add_entropy(srv->SslEntropyFile); add_entropy(RAND_file_name(path, sizeof(path))); /* * load entropy from egd sockets */ #ifdef HAVE_RAND_EGD add_entropy(getenv("EGDSOCKET")); snprintf(path, sizeof(path), "%s/.entropy", NONULL(Homedir)); add_entropy(path); add_entropy("/tmp/entropy"); #endif /* * shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof(path))); if (!RAND_status()) { LOG(SPOCP_ERR) traceLog(LOG_ERR, "Failed to find enough entropy on your system"); return 0; } } /* * Initialize with DH parameters if supplied */ if (srv->dhFile) { if (init_dh(ctx, (unsigned char *) srv->dhFile) == FALSE) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing DH"); SSL_CTX_free(ctx); return 0; } else LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing DH OK"); } /* * and a RSA key too */ if (generate_eph_rsa_key(ctx, 512) == FALSE) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error initializing RSA key"); SSL_CTX_free(ctx); return 0; } else LOG(SPOCP_ERR) traceLog(LOG_ERR,"Initializing RSA key OK"); /* * Set up certificates and keys */ if (srv->certificateFile != NULL) { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Certificate File"); if (!SSL_CTX_use_certificate_chain_file (ctx, srv->certificateFile)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_use_certificate_file"); SSL_CTX_free(ctx); return 0; } } if (srv->privateKey != NULL) { if (srv->passwd) { SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) srv-> passwd); SSL_CTX_set_default_passwd_cb(ctx, password_cb); } LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Private Key File"); r = SSL_CTX_use_PrivateKey_file(ctx, srv->privateKey, SSL_FILETYPE_PEM); if (r == 0) { e = ERR_get_error(); ERR_error_string_n(e, errorstr, 1024); LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_use_PrivateKey_file"); LOG(SPOCP_ERR) traceLog(LOG_ERR,"%s", errorstr); SSL_CTX_free(ctx); return 0; } } if (srv->caList != NULL) { LOG(SPOCP_INFO) traceLog(LOG_INFO,"Reading Trusted CAs File"); if (!SSL_CTX_load_verify_locations(ctx, srv->caList, 0)) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"Error in SSL_CTX_load_verify_locations"); SSL_CTX_free(ctx); return 0; } } if (srv->clientcert == NONE) SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback_ok); else { int i = SSL_VERIFY_PEER; if (srv->clientcert == HARD) i |= SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(ctx, i, verify_callback); } SSL_CTX_set_verify_depth(ctx, srv->sslverifydepth); SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); if (SSL_CTX_set_cipher_list(ctx, CIPHER_LIST) != 1) { LOG(SPOCP_ERR) traceLog(LOG_ERR,"No valid ciphers in cipherlist"); SSL_CTX_free(ctx); return 0; } LOG(SPOCP_DEBUG) traceLog(LOG_DEBUG,"Initialised TLS"); return ctx; }