Пример #1
0
static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
	     char **retp)
	{
	int ret=0;
	BY_DIR *ld;
	char *dir = NULL;

	ld=(BY_DIR *)ctx->method_data;

	switch (cmd)
		{
	case X509_L_ADD_DIR:
		if (argl == X509_FILETYPE_DEFAULT)
			{
			dir=(char *)Getenv(X509_get_default_cert_dir_env());
			if (dir)
				ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
			else
				ret=add_cert_dir(ld,X509_get_default_cert_dir(),
					X509_FILETYPE_PEM);
			if (!ret)
				{
				X509err(X509_F_DIR_CTRL,X509_R_LOADING_CERT_DIR);
				}
			}
		else
			ret=add_cert_dir(ld,argp,(int)argl);
		break;
		}
	return(ret);
	}
Пример #2
0
extern "C" const char* CryptoNative_GetX509RootStorePath()
{
    const char* dir = getenv(X509_get_default_cert_dir_env());

    if (!dir)
    {
        dir = X509_get_default_cert_dir();
    }

    return dir;
}
Пример #3
0
int _setupSystemCA(SSL_CTX* context, char* err, size_t err_len) {
#if !defined(_WIN32) && !defined(__APPLE__)
    // On non-Windows/non-Apple platforms, the OpenSSL libraries should have been
    // configured with default locations for CA certificates.
    if (SSL_CTX_set_default_verify_paths(context) != 1) {
        snprintf(err,
                 err_len,
                 "error loading system CA certificates "
                 "(default certificate file: %s default certificate path: %s )",
                 X509_get_default_cert_file(),
                 X509_get_default_cert_dir());
        return 0;
    }
    return 1;
#else

    X509_STORE* verifyStore = SSL_CTX_get_cert_store(context);
    if (!verifyStore) {
        snprintf(err,
                 err_len,
                 "no X509 store found for SSL context while loading "
                 "system certificates");
        return 0;
    }
#if defined(_WIN32)
    int status = importCertStoreToX509_STORE(
        L"root", CERT_SYSTEM_STORE_CURRENT_USER, verifyStore, err, err_len);
    if (!status)
        return status;
    return importCertStoreToX509_STORE(
        L"CA", CERT_SYSTEM_STORE_CURRENT_USER, verifyStore, err, err_len);
#elif defined(__APPLE__)
    return importKeychainToX509_STORE(verifyStore, err, err_len);
#endif
#endif
}
Пример #4
0
static char *global_options(CMD cmd, char *opt, char *arg) {

    if(cmd==CMD_DEFAULT || cmd==CMD_HELP) {
        log_raw("Global options");
    }

    /* CApath */
    switch(cmd) {
    case CMD_INIT:
#if 0
        options.ca_dir=(char *)X509_get_default_cert_dir();
#endif
        options.ca_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CApath"))
            break;
        if(arg[0]) /* not empty */
            options.ca_dir=stralloc(arg);
        else
            options.ca_dir=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
#if 0
        log_raw("%-15s = %s", "CApath",
            options.ca_dir ? options.ca_dir : "(none)");
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = CA certificate directory for 'verify' option",
            "CApath");
        break;
    }

    /* CAfile */
    switch(cmd) {
    case CMD_INIT:
#if 0
        options.ca_file=(char *)X509_get_default_certfile();
#endif
        options.ca_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CAfile"))
            break;
        if(arg[0]) /* not empty */
            options.ca_file=stralloc(arg);
        else
            options.ca_file=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
#if 0
        log_raw("%-15s = %s", "CAfile",
            options.ca_file ? options.ca_file : "(none)");
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = CA certificate file for 'verify' option",
            "CAfile");
        break;
    }

    /* cert */
    switch(cmd) {
    case CMD_INIT:
#ifdef CONFDIR
        options.cert=CONFDIR "/stunnel.pem";
#else
        options.cert="stunnel.pem";
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "cert"))
            break;
        options.cert=stralloc(arg);
        options.option.cert=1;
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "cert", options.cert);
        break;
    case CMD_HELP:
        log_raw("%-15s = certificate chain", "cert");
        break;
    }

    /* chroot */
#ifdef HAVE_CHROOT
    switch(cmd) {
    case CMD_INIT:
        options.chroot_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "chroot"))
            break;
        options.chroot_dir=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = directory to chroot stunnel process", "chroot");
        break;
    }
#endif /* HAVE_CHROOT */

    /* ciphers */
    switch(cmd) {
    case CMD_INIT:
        options.cipher_list=SSL_DEFAULT_CIPHER_LIST;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "ciphers"))
            break;
        options.cipher_list=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "ciphers", SSL_DEFAULT_CIPHER_LIST);
        break;
    case CMD_HELP:
        log_raw("%-15s = list of permitted SSL ciphers", "ciphers");
        break;
    }

    /* client */
    switch(cmd) {
    case CMD_INIT:
        options.option.client=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "client"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.client=1;
        else if(!strcasecmp(arg, "no"))
            options.option.client=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no client mode (remote service uses SSL)",
            "client");
        break;
    }

    /* CRLpath */
    switch(cmd) {
    case CMD_INIT:
        options.crl_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CRLpath"))
            break;
        if(arg[0]) /* not empty */
            options.crl_dir=stralloc(arg);
        else
            options.crl_dir=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = CRL directory", "CRLpath");
        break;
    }

    /* CRLfile */
    switch(cmd) {
    case CMD_INIT:
        options.crl_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CRLfile"))
            break;
        if(arg[0]) /* not empty */
            options.crl_file=stralloc(arg);
        else
            options.crl_file=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = CRL file", "CRLfile");
        break;
    }

    /* debug */
    switch(cmd) {
    case CMD_INIT:
        options.debug_level=5;
#if !defined (USE_WIN32) && !defined (__vms)
        options.facility=LOG_DAEMON;
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "debug"))
            break;
        if(!parse_debug_level(arg))
            return "Illegal debug argument";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %d", "debug", options.debug_level);
        break;
    case CMD_HELP:
        log_raw("%-15s = [facility].level (e.g. daemon.info)", "debug");
        break;
    }

    /* EGD is only supported when compiled with OpenSSL 0.9.5a or later */
#if SSLEAY_VERSION_NUMBER >= 0x0090581fL
    switch(cmd) {
    case CMD_INIT:
        options.egd_sock=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "EGD"))
            break;
        options.egd_sock=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef EGD_SOCKET
        log_raw("%-15s = %s", "EGD", EGD_SOCKET);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = path to Entropy Gathering Daemon socket", "EGD");
        break;
    }
#endif /* OpenSSL 0.9.5a */

    /* foreground */
#ifndef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.option.syslog=0;
        options.option.foreground=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "foreground"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.foreground=1;
        else if(!strcasecmp(arg, "no"))
            options.option.foreground=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no foreground mode (don't fork, log to stderr)",
            "foreground");
        break;
    }
#endif

    /* key */
    switch(cmd) {
    case CMD_INIT:
        options.key=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "key"))
            break;
        options.key=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "key", options.cert); /* set in stunnel.c */
        break;
    case CMD_HELP:
        log_raw("%-15s = certificate private key", "key");
        break;
    }

    /* options */
    switch(cmd) {
    case CMD_INIT:
        options.ssl_options=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "options"))
            break;
        if(!parse_ssl_option(arg))
            return "Illegal SSL option";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = SSL option", "options");
        log_raw("%18sset an SSL option", "");
        break;
    }

    /* output */
    switch(cmd) {
    case CMD_INIT:
        options.output_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "output"))
            break;
        options.output_file=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = file to append log messages", "output");
        break;
    }

    /* pid */
#ifndef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.pidfile=PIDFILE;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "pid"))
            break;
        if(arg[0]) /* is argument not empty? */
            options.pidfile=stralloc(arg);
        else
            options.pidfile=NULL; /* empty -> do not create a pid file */
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "pid", PIDFILE);
        break;
    case CMD_HELP:
        log_raw("%-15s = pid file (empty to disable creating)", "pid");
        break;
    }
#endif

    /* RNDbytes */
    switch(cmd) {
    case CMD_INIT:
        options.random_bytes=RANDOM_BYTES;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDbytes"))
            break;
        options.random_bytes=atoi(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %d", "RNDbytes", RANDOM_BYTES);
        break;
    case CMD_HELP:
        log_raw("%-15s = bytes to read from random seed files", "RNDbytes");
        break;
    }

    /* RNDfile */
    switch(cmd) {
    case CMD_INIT:
        options.rand_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDfile"))
            break;
        options.rand_file=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef RANDOM_FILE
        log_raw("%-15s = %s", "RNDfile", RANDOM_FILE);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = path to file with random seed data", "RNDfile");
        break;
    }

    /* RNDoverwrite */
    switch(cmd) {
    case CMD_INIT:
        options.option.rand_write=1;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDoverwrite"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.rand_write=1;
        else if(!strcasecmp(arg, "no"))
            options.option.rand_write=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = yes", "RNDoverwrite");
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no overwrite seed datafiles with new random data",
            "RNDoverwrite");
        break;
    }

    /* service */
    switch(cmd) {
    case CMD_INIT:
        local_options.servname=stralloc("stunnel");
#ifdef USE_WIN32
        options.win32_service="stunnel";
        options.win32_name="stunnel " VERSION " on Win32";
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "service"))
            break;
        local_options.servname=stralloc(arg);
#ifdef USE_WIN32
        options.win32_service=stralloc(arg);
        {
            char tmpstr[STRLEN];

            safecopy(tmpstr, "stunnel " VERSION " on Win32 (");
            safeconcat(tmpstr, arg);
            safeconcat(tmpstr, ")");
            options.win32_name=stralloc(tmpstr);
        }
#endif
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef USE_WIN32
        log_raw("%-15s = %s", "service", options.win32_service);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = service name", "service");
        break;
    }

    /* session */
    switch(cmd) {
    case CMD_INIT:
        options.session_timeout=300;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "session"))
            break;
        if(atoi(arg)>0)
            options.session_timeout=atoi(arg);
        else
            return "Illegal session timeout";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %ld seconds", "session", options.session_timeout);
        break;
    case CMD_HELP:
        log_raw("%-15s = session cache timeout (in seconds)", "session");
        break;
    }

#ifndef USE_WIN32
    /* setgid */
    switch(cmd) {
    case CMD_INIT:
        options.setgid_group=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "setgid"))
            break;
        options.setgid_group=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = groupname for setgid()", "setgid");
        break;
    }
#endif

#ifndef USE_WIN32
    /* setuid */
    switch(cmd) {
    case CMD_INIT:
        options.setuid_user=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "setuid"))
            break;
        options.setuid_user=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = username for setuid()", "setuid");
        break;
    }
#endif

    /* socket */
    switch(cmd) {
    case CMD_INIT:
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "socket"))
            break;
        if(!parse_socket_option(arg))
            return "Illegal socket option";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = a|l|r:option=value[:value]", "socket");
        log_raw("%18sset an option on accept/local/remote socket", "");
        break;
    }

    /* taskbar */
#ifdef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.option.taskbar=1;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "taskbar"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.taskbar=1;
        else if(!strcasecmp(arg, "no"))
            options.option.taskbar=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = yes", "taskbar");
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no enable the taskbar icon", "taskbar");
        break;
    }
#endif

    /* verify */
    switch(cmd) {
    case CMD_INIT:
        options.verify_level=-1;
        options.verify_use_only_my=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "verify"))
            break;
        options.verify_level=SSL_VERIFY_NONE;
        switch(atoi(arg)) {
        case 3:
            options.verify_use_only_my=1;
        case 2:
            options.verify_level|=SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
        case 1:
            options.verify_level|=SSL_VERIFY_PEER;
        case 0:
            return NULL; /* OK */
        default:
            return "Bad verify level";
        }
    case CMD_DEFAULT:
        log_raw("%-15s = none", "verify");
        break;
    case CMD_HELP:
        log_raw("%-15s = level of peer certificate verification", "verify");
        log_raw("%18slevel 1 - verify peer certificate if present", "");
        log_raw("%18slevel 2 - require valid peer certificate always", "");
        log_raw("%18slevel 3 - verify peer with locally installed certificate",
        "");
        break;
    }

    if(cmd==CMD_EXEC)
        return option_not_found;
    return NULL; /* OK */
}
Пример #5
0
int
main(int argc, char *argv[], char *env[])
{
	struct sockaddr_storage from;
	int on = 1;
	socklen_t fromlen;
	register int ch;
	int i;

#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)
	int tos = -1;
#endif

	initsetproctitle(argc, argv, env);

	pfrontp = pbackp = ptyobuf;
	netip = netibuf;

#ifdef USE_SSL
	/* we need to know the fullpath to the location of the
	 * certificate that we will be running with as we cannot
	 * be sure of the cwd when we are launched
	 */
	sprintf(cert_filepath,"%s/%s",X509_get_default_cert_dir(),
	        "telnetd.pem");
	ssl_cert_file=cert_filepath;
	ssl_key_file=NULL;
#endif /* USE_SSL */

	while ((ch = getopt(argc, argv, "d:a:e:lhnNr:I:D:B:sS:a:X:L:z:")) != EOF) {
		switch(ch) {

#ifdef USE_SSL
                case 'z':
		        { 
			char *origopt;

			origopt=strdup(optarg);
			optarg=strtok(origopt,",");

			while(optarg!=NULL) {

		        if (strcmp(optarg, "debug") == 0 ) {
			    ssl_debug_flag=1;
			} else if (strcmp(optarg, "ssl") == 0 ) {
			    ssl_only_flag=1;
			} else if (strcmp(optarg, "certsok") == 0 ) {
			    ssl_certsok_flag=1;
			} else if ( (strcmp(optarg, "!ssl") == 0) ||
		             (strcmp(optarg, "nossl") == 0) ) {
			    /* we may want to switch SSL negotiation off
			     * for testing or other reasons 
			     */
			    ssl_disabled_flag=1;
			} else if (strcmp(optarg, "certrequired") == 0 ) {
			    ssl_cert_required=1;
			} else if (strcmp(optarg, "secure") == 0 ) {
			    ssl_secure_flag=1;
			} else if (strncmp(optarg, "verify=", 
			                strlen("verify=")) == 0 ) {
			    ssl_verify_flag=atoi(optarg+strlen("verify="));
			} else if (strncmp(optarg, "cert=", 
			                strlen("cert=")) == 0 ) {
			    ssl_cert_file=optarg+strlen("cert=");
			} else if (strncmp(optarg, "key=", 
			                strlen("key=")) == 0 ) {
			    ssl_key_file=optarg+strlen("key=");
			} else if (strncmp(optarg,"cipher=",
			                strlen("cipher="))==0) {
			    ssl_cipher_list=optarg+strlen("cipher=");
			} else {
			    /* report when we are given rubbish so that
			     * if the user makes a mistake they have to
			     * correct it!
			     */
			    fprintf(stderr,"Unknown SSL option %s\n",optarg);
			    fflush(stderr);
			    exit(1);
			}

			/* get the next one ... */
                        optarg=strtok(NULL,",");

			}

			/*
			if (origopt!=NULL)
			    free(origopt);
			*/

			}
			break;
#endif /* USE_SSL */

#ifdef	AUTHENTICATE
		case 'a':
			/*
			 * Check for required authentication level
			 */
			if (strcmp(optarg, "debug") == 0) {
				extern int auth_debug_mode;
				auth_debug_mode = 1;
			} else if (strcasecmp(optarg, "none") == 0) {
				auth_level = 0;
			} else if (strcasecmp(optarg, "other") == 0) {
				auth_level = AUTH_OTHER;
			} else if (strcasecmp(optarg, "user") == 0) {
				auth_level = AUTH_USER;
			} else if (strcasecmp(optarg, "valid") == 0) {
				auth_level = AUTH_VALID;
			} else if (strcasecmp(optarg, "off") == 0) {
				/*
				 * This hack turns off authentication
				 */
				auth_level = -1;
			} else {
				fprintf(stderr,
			    "telnetd: unknown authorization level for -a\n");
			}
			break;
#endif	/* AUTHENTICATE */

#ifdef BFTPDAEMON
		case 'B':
			bftpd++;
			break;
#endif /* BFTPDAEMON */

		case 'd':
			if (strcmp(optarg, "ebug") == 0) {
				debug++;
				break;
			}
			usage();
			/* NOTREACHED */
			break;

#ifdef DIAGNOSTICS
		case 'D':
			/*
			 * Check for desired diagnostics capabilities.
			 */
			if (!strcmp(optarg, "report")) {
				diagnostic |= TD_REPORT|TD_OPTIONS;
			} else if (!strcmp(optarg, "exercise")) {
				diagnostic |= TD_EXERCISE;
			} else if (!strcmp(optarg, "netdata")) {
				diagnostic |= TD_NETDATA;
			} else if (!strcmp(optarg, "ptydata")) {
				diagnostic |= TD_PTYDATA;
			} else if (!strcmp(optarg, "options")) {
				diagnostic |= TD_OPTIONS;
			} else {
				usage();
				/* NOT REACHED */
			}
			break;
#endif /* DIAGNOSTICS */

#ifdef	AUTHENTICATE
		case 'e':
			if (strcmp(optarg, "debug") == 0) {
				extern int auth_debug_mode;
				auth_debug_mode = 1;
				break;
			}
			usage();
			/* NOTREACHED */
			break;
#endif	/* AUTHENTICATE */

		case 'h':
			hostinfo = 0;
			break;

#ifdef	LINEMODE
		case 'l':
			alwayslinemode = 1;
			break;
#endif	/* LINEMODE */

		case 'L':
			loginprg = strdup(optarg);
			/* XXX what if strdup fails? */
			break;

		case 'n':
			keepalive = 0;
			break;

		case 'N':
		  numeric_hosts = 1;
		  break;

#ifdef	SecurID
		case 's':
			/* SecurID required */
			require_SecurID = 1;
			break;
#endif	/* SecurID */
		case 'S':
#ifdef	HAS_GETTOS
			if ((tos = parsetos(optarg, "tcp")) < 0)
				fprintf(stderr, "%s%s%s\n",
					"telnetd: Bad TOS argument '", optarg,
					"'; will try to use default TOS");
#else
			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
						"-S flag not supported\n");
#endif
			break;

#ifdef	AUTHENTICATE
		case 'X':
			/*
			 * Check for invalid authentication types
			 */
			auth_disable_name(optarg);
			break;
#endif	/* AUTHENTICATE */

		default:
			fprintf(stderr, "telnetd: %c: unknown option\n", ch);
			/* FALLTHROUGH */
		case '?':
			usage();
			/* NOTREACHED */
		}
	}

#ifdef USE_SSL

        if (ssl_secure_flag || ssl_cert_required || ssl_certsok_flag) {
	    /* in secure mode we *must* switch on the base level
	     * verify checking otherwise we cannot abort connections
	     * at the right place!
	     */
	    if (ssl_verify_flag==0)
		ssl_verify_flag=1;
	}

	/* if we are not running in debug then any error
	 * stuff from SSL debug *must* not go down
	 * the socket (which 0,1,2 are all pointing to by
	 * default)
	 */
	if (ssl_debug_flag)
	    ssl_log_file="/telnetd.log";

	if (!do_ssleay_init(1)) {
	  if (bio_err!=NULL) {
	    BIO_printf(bio_err,"do_ssleay_init() failed\n");
	    ERR_print_errors(bio_err);
	  } else {
	    fflush(stderr);
	    fprintf(stderr,"do_ssleay_init() failed\n");
	    ERR_print_errors_fp(stderr);
	  }
	  exit(1);
	}

	if (ssl_debug_flag) {
	  BIO_printf(bio_err,"secure %d certrequired %d verify %d\n",
	      ssl_secure_flag,ssl_cert_required,ssl_verify_flag);
	  for(i=0;i<argc;i++)
	      BIO_printf(bio_err,"argv[%d]=\"%s\"\n",i,argv[i]);
	}

#endif /* USE_SSL */

	argc -= optind;
	argv += optind;

	if (debug) {
		if (argc > 1) {
			usage();
			/* NOTREACHED */
		}

		wait_for_connection((argc == 1) ? *argv : "telnet");
	}

	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
	fromlen = sizeof (from);
	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
		fatalperror(2, "getpeername");
	}
	if (keepalive &&
	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
	}

#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)
	{
# if	defined(HAS_GETTOS)
		struct tosent *tp;
		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
			tos = tp->t_tos;
# endif
		if (tos < 0)
			tos = 020;	/* Low Delay bit */
		if (tos
		   && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
		   && (errno != ENOPROTOOPT) )
			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
	}
#endif	/* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */

#ifdef USE_SSL
        /* do the SSL stuff now ... before we play with pty's */
	SSL_set_fd(ssl_con,0);

	if (ssl_only_flag) {
	    /* hmm ... only when running talking to things like
	     * https servers should we hit this code and then
	     * we really don't care *who* we talk to :-)
	     */
	    SSL_set_verify(ssl_con,ssl_verify_flag,NULL);

	    if (SSL_accept(ssl_con) <= 0) {
		static char errbuf[1024];
	    
	        sprintf(errbuf,"SSL_accept error %s\n",
		    ERR_error_string(ERR_get_error(),NULL));

		syslog(LOG_WARNING, "%s", errbuf);

		BIO_printf(bio_err,"%s",errbuf);

		/* go to sleep to make sure we are noticed */
		sleep(10);
		SSL_free(ssl_con);

		_exit(1);
	    } else {
		ssl_active_flag=1;
	    }
	}
#endif /* USE_SSL */

	net = 0;
	netopen();
	doit((struct sockaddr *)&from, fromlen);
	/* NOTREACHED */
	return 0;
}  /* end of main */