Пример #1
0
GSList *
cmdline_match_holding(
    GSList *dumpspec_list)
{
    dumpspec_t *de;
    GSList *li, *hi;
    GSList *holding_files;
    GSList *matching_files = NULL;
    dumpfile_t file;

    holding_files = holding_get_files(NULL, 1);

    for (hi = holding_files; hi != NULL; hi = hi->next) {
	/* TODO add level */
	if (!holding_file_get_dumpfile((char *)hi->data, &file)) continue;
        if (file.type != F_DUMPFILE) {
	    dumpfile_free_data(&file);
	    continue;
	}
        for (li = dumpspec_list; li != NULL; li = li->next) {
	    de = (dumpspec_t *)(li->data);
            if (de->host && de->host[0] && !match_host(de->host, file.name)) continue;
            if (de->disk && de->disk[0] && !match_disk(de->disk, file.disk)) continue;
            if (de->datestamp && de->datestamp[0] && !match_datestamp(de->datestamp, file.datestamp)) continue;
            matching_files = g_slist_append(matching_files, g_strdup((char *)hi->data));
            break;
        }
	dumpfile_free_data(&file);
    }

    slist_free_full(holding_files, g_free);

    return matching_files;
}
Пример #2
0
		bool is_allowed_v6(const addr_v6 &remote, std::list<std::string> &errors) {
			if (!cached)
				refresh(errors);
			BOOST_FOREACH(const host_record_v6 &r, entries_v6) {
				if (match_host(r.addr, r.mask, remote))
					return true;
			}
			return false;
		}
Пример #3
0
static int check_host_name(const char *name, const char *host)
{
	if (!strcasecmp(name, host))
		return 0;

	if (match_host(name, host) < 0)
		return -1;

	return 0;
}
Пример #4
0
		bool is_allowed_v4(const unsigned long &remote, std::list<std::string> &errors) {
			errors.push_back(strEx::wstring_to_string(strEx::itos(remote)));
			if (entries.empty())
				return true;
			if (!cached)
				refresh(errors);
			BOOST_FOREACH(const host_record &r, entries) {
				if (match_host(r, remote))
					return true;
			}
			return false;
		}
Пример #5
0
static gboolean
test_make_exact_host_expression(void)
{
    gboolean ok = TRUE;
    guint i, j;
    const char *test_strs[] = {
	"host",
	"host.org",
	"host.host.org",
	/* note that these will inter-match: */
	/*
	".host",
	".host.org",
	".host.host.org",
	"host.",
	"host.org.",
	"host.host.org.",
	*/
	"org",
	"^host",
	"host$",
	"^host$",
	"ho[s]t",
	"ho[!s]t",
	"ho\\st",
	"ho/st",
	"ho?t",
	"h*t",
	"h**t",
    };

    for (i = 0; i < G_N_ELEMENTS(test_strs); i++) {
	for (j = 0; j < G_N_ELEMENTS(test_strs); j++) {
	    char *expr = make_exact_host_expression(test_strs[i]);
	    gboolean matched = match_host(expr, test_strs[j]);
	    if (!!matched != !!(i == j)) {
		ok = FALSE;
		if (matched) {
		    g_fprintf(stderr, "expr %s for str %s unexpectedly matched %s\n",
			    expr, test_strs[i], test_strs[j]);
		} else {
		    g_fprintf(stderr, "expr %s for str %s should have matched %s\n",
			    expr, test_strs[i], test_strs[j]);
		}
	    }
	    amfree(expr);
	}
    }

    return ok;
}
Пример #6
0
/*
 * Return the set of dumps that match *all* of the given patterns (we consider
 * an empty pattern to match .*, though).  If 'ok' is true, will only match
 * dumps with SUCCESS status.
 *
 * Returns a newly allocated list of results, where all strings are also newly
 * allocated.  Apparently some part of Amanda leaks under this condition.
 */
find_result_t *
dumps_match(
    find_result_t *output_find,
    char *hostname,
    char *diskname,
    char *datestamp,
    char *level,
    int ok)
{
    find_result_t *cur_result;
    find_result_t *matches = NULL;

    for(cur_result=output_find;
	cur_result;
	cur_result=cur_result->next) {
	char level_str[NUM_STR_SIZE];
	g_snprintf(level_str, sizeof(level_str), "%d", cur_result->level);
	if((!hostname || *hostname == '\0' || match_host(hostname, cur_result->hostname)) &&
	   (!diskname || *diskname == '\0' || match_disk(diskname, cur_result->diskname)) &&
	   (!datestamp || *datestamp== '\0' || match_datestamp(datestamp, cur_result->timestamp)) &&
	   (!level || *level== '\0' || match_level(level, level_str)) &&
	   (!ok || g_str_equal(cur_result->status, "OK")) &&
	   (!ok || g_str_equal(cur_result->dump_status, "OK"))){

	    find_result_t *curmatch = g_new0(find_result_t, 1);
	    memcpy(curmatch, cur_result, sizeof(find_result_t));

	    curmatch->timestamp = cur_result->timestamp;
	    curmatch->write_timestamp = cur_result->write_timestamp;
	    curmatch->hostname = cur_result->hostname;
	    curmatch->diskname = cur_result->diskname;
	    curmatch->level = cur_result->level;
	    curmatch->label = cur_result->label? cur_result->label : NULL;
	    curmatch->filenum = cur_result->filenum;
	    curmatch->sec = cur_result->sec;
	    curmatch->kb = cur_result->kb;
	    curmatch->bytes = cur_result->bytes;
	    curmatch->orig_kb = cur_result->orig_kb;
	    curmatch->status = cur_result->status;
	    curmatch->dump_status = cur_result->dump_status;
	    curmatch->message = cur_result->message;
	    curmatch->partnum = cur_result->partnum;
	    curmatch->totalparts = cur_result->totalparts;
	    curmatch->next = matches;
	    matches = curmatch;
	}
    }

    return(matches);
}
Пример #7
0
/* Match host names according to RFC 2818 rules */
static int match_host(const char *pattern, const char *host)
{
	for (;;) {
		char c = tolower(*pattern++);

		if (c == '\0')
			return *host ? -1 : 0;

		if (c == '*') {
			c = *pattern;
			/* '*' at the end matches everything left */
			if (c == '\0')
				return 0;

	/*
	 * We've found a pattern, so move towards the next matching
	 * char. The '.' is handled specially because wildcards aren't
	 * allowed to cross subdomains.
	 */

			while(*host) {
				char h = tolower(*host);
				if (c == h)
					return match_host(pattern, host++);
				if (h == '.')
					return match_host(pattern, host);
				host++;
			}
			return -1;
		}

		if (c != tolower(*host++))
			return -1;
	}

	return -1;
}
Пример #8
0
static int match_urls(const struct url_info *url,
		      const struct url_info *url_prefix,
		      struct urlmatch_item *match)
{
	/*
	 * url_prefix matches url if the scheme, host and port of url_prefix
	 * are the same as those of url and the path portion of url_prefix
	 * is the same as the path portion of url or it is a prefix that
	 * matches at a '/' boundary.  If url_prefix contains a user name,
	 * that must also exactly match the user name in url.
	 *
	 * If the user, host, port and path match in this fashion, the returned
	 * value is the length of the path match including any implicit
	 * final '/'.  For example, "http://[email protected]/path" is matched by
	 * "http://example.com" with a path length of 1.
	 *
	 * If there is a match and exactusermatch is not NULL, then
	 * *exactusermatch will be set to true if both url and url_prefix
	 * contained a user name or false if url_prefix did not have a
	 * user name.  If there is no match *exactusermatch is left untouched.
	 */
	char usermatched = 0;
	size_t pathmatchlen;

	if (!url || !url_prefix || !url->url || !url_prefix->url)
		return 0;

	/* check the scheme */
	if (url_prefix->scheme_len != url->scheme_len ||
	    strncmp(url->url, url_prefix->url, url->scheme_len))
		return 0; /* schemes do not match */

	/* check the user name if url_prefix has one */
	if (url_prefix->user_off) {
		if (!url->user_off || url->user_len != url_prefix->user_len ||
		    strncmp(url->url + url->user_off,
			    url_prefix->url + url_prefix->user_off,
			    url->user_len))
			return 0; /* url_prefix has a user but it's not a match */
		usermatched = 1;
	}

	/* check the host */
	if (!match_host(url, url_prefix))
		return 0; /* host names do not match */

	/* check the port */
	if (url_prefix->port_len != url->port_len ||
	    strncmp(url->url + url->port_off,
		    url_prefix->url + url_prefix->port_off, url->port_len))
		return 0; /* ports do not match */

	/* check the path */
	pathmatchlen = url_match_prefix(
		url->url + url->path_off,
		url_prefix->url + url_prefix->path_off,
		url_prefix->url_len - url_prefix->path_off);
	if (!pathmatchlen)
		return 0; /* paths do not match */

	if (match) {
		match->hostmatch_len = url_prefix->host_len;
		match->pathmatch_len = pathmatchlen;
		match->user_matched = usermatched;
	}

	return 1;
}
Пример #9
0
static gboolean
test_match_host(void)
{
    gboolean ok = TRUE;
    struct {
	char *expr, *str;
	gboolean should_match;
    } tests[] = {
	/* from the amanda(8) manpage */
	{ "hosta", "hosta", TRUE },
	{ "hosta", "foo.hosta.org", TRUE },
	{ "hosta", "hoSTA.dOMAIna.ORG", TRUE },
	{ "hosta", "hostb", FALSE },
	{ "hOsta", "hosta", TRUE },
	{ "hOsta", "foo.hosta.org", TRUE },
	{ "hOsta", "hoSTA.dOMAIna.ORG", TRUE },
	{ "hOsta", "hostb", FALSE },

	{ "host", "host", TRUE },
	{ "host", "hosta", FALSE },

	{ "host?", "hosta", TRUE },
	{ "host?", "hostb", TRUE },
	{ "host?", "host", FALSE },
	{ "host?", "hostabc", FALSE },

	{ "ho*na", "hona", TRUE },
	{ "ho*na", "hoina", TRUE },
	{ "ho*na", "hoina.org", TRUE },
	{ "ho*na", "ns.hoina.org", TRUE },
	{ "ho*na", "ho.aina.org", FALSE },

	{ "ho**na", "hona", TRUE },
	{ "ho**na", "hoina", TRUE },
	{ "ho**na", "hoina.org", TRUE },
	{ "ho**na", "ns.hoina.org", TRUE },
	{ "ho**na", "ho.aina.org", TRUE },

	{ "^hosta", "hosta", TRUE },
	{ "^hosta", "hosta.org", TRUE },
	{ "^hosta", "hostabc", FALSE },
	{ "^hosta", "www.hosta", FALSE },
	{ "^hosta", "www.hosta.org", FALSE },

	{ "/opt", "opt", FALSE },

	{ ".hosta.", "hosta", TRUE },
	{ ".hosta.", "foo.hosta", TRUE },
	{ ".hosta.", "hosta.org", TRUE },
	{ ".hosta.", "foo.hosta.org", TRUE },
	{ "/hosta", "hosta", FALSE },
	{ "/hosta", "foo.hosta", FALSE },
	{ "/hosta", "hosta.org", FALSE },
	{ "/hosta", "foo.hosta.org", FALSE },

	{ ".opt.", "opt", TRUE },
	{ ".opt.", "www.opt", TRUE },
	{ ".opt.", "www.opt.com", TRUE },
	{ ".opt.", "opt.com", TRUE },

	/* other examples */
	{ "^hosta$", "hosta", TRUE },
	{ "^hosta$", "foo.hosta", FALSE },
	{ "^hosta$", "hosta.org", FALSE },
	{ "^hosta$", "foo.hosta.org", FALSE },

	{ "^lu.vis.ta$", "lu.vis.ta", TRUE },
	{ "^lu.vis.ta$", "lu-vis.ta", FALSE },
	{ "^lu.vis.ta$", "luvista", FALSE },
	{ "^lu.vis.ta$", "foo.lu.vis.ta", FALSE },
	{ "^lu.vis.ta$", "lu.vis.ta.org", FALSE },
	{ "^lu.vis.ta$", "foo.lu.vis.ta.org", FALSE },

	{ "mo[st]a", "mota", TRUE },
	{ "mo[st]a", "mosa", TRUE },
	{ "mo[st]a", "mosta", FALSE },
	{ "mo[!st]a", "mota", FALSE },
	{ "mo[!st]a", "moma", TRUE },
	{ "mo[!st]a", "momma", FALSE },

	{ "host[acd]", "hosta", TRUE },
	{ "host[acd]", "hostb", FALSE },
	{ "host[acd]", "hostc", TRUE },
	{ "host[!acd]", "hosta", FALSE },
	{ "host[!acd]", "hostb", TRUE },
	{ "host[!acd]", "hostc", FALSE },

	{ "toast", "www.toast.com", TRUE },
	{ ".toast", "www.toast.com", TRUE },
	{ "toast.", "www.toast.com", TRUE },
	{ ".toast.", "www.toast.com", TRUE },

	{ NULL, NULL, FALSE },
    }, *t;

    for (t = tests; t->expr; t++) {
	gboolean matched = match_host(t->expr, t->str);
	if (!!matched != !!t->should_match) {
	    ok = FALSE;
	    if (t->should_match) {
		g_fprintf(stderr, "%s should have matched host expr %s\n",
			t->str, t->expr);
	    } else {
		g_fprintf(stderr, "%s unexpectedly matched host expr %s\n",
			t->str, t->expr);
	    }
	}
    }

    return ok;
}
Пример #10
0
int main(int ac, char **av)
{
    extern char *optarg;
    extern int optind;
    int opt, sock_in, sock_out, newsock, i, pid = 0, on = 1;
    socklen_t aux;
    int remote_major, remote_minor;
    int perm_denied = 0;
    int ret;
    fd_set fdset;
#ifdef HAVE_IPV6_SMTH
    struct sockaddr_in6 sin;
#else
    struct sockaddr_in sin;
#endif
    char buf[100];              /* Must not be larger than remote_version. */
    char remote_version[100];   /* Must be at least as big as buf. */
    char addr[STRLEN];
    char *comment;
    char *ssh_remote_version_string = NULL;
    FILE *f;

#if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
    struct linger linger;
#endif                          /* SO_LINGER */
    int done;

    chdir(BBSHOME);
    /* Save argv[0]. */
    saved_argv = av;
    if (strchr(av[0], '/'))
        av0 = strrchr(av[0], '/') + 1;
    else
        av0 = av[0];

    /* Prevent core dumps to avoid revealing sensitive information. */
    signals_prevent_core();

    /* Set SIGPIPE to be ignored. */
    signal(SIGPIPE, SIG_IGN);

    /* Initialize configuration options to their default values. */
    initialize_server_options(&options);
    addr[0]=0;

    /* Parse command-line arguments. */
    while ((opt = getopt(ac, av, "f:a:p:b:k:h:g:diqV:")) != EOF) {
        switch (opt) {
        case 'f':
            config_file_name = optarg;
            break;
        case 'd':
            debug_flag = 1;
            break;
        case 'i':
            inetd_flag = 1;
            break;
        case 'q':
            options.quiet_mode = 1;
            break;
        case 'b':
            options.server_key_bits = atoi(optarg);
            break;
        case 'a':
            if(optarg[0])
                snprintf(addr,STRLEN,"%s",optarg);
            break;
        case 'p':
            if(isdigit(optarg[0]))
                options.port=atoi(optarg);
            break;
        case 'g':
            options.login_grace_time = atoi(optarg);
            break;
        case 'k':
            options.key_regeneration_time = atoi(optarg);
            break;
        case 'h':
            options.host_key_file = optarg;
            break;
        case 'V':
            ssh_remote_version_string = optarg;
            break;
        case '?':
        default:
#ifdef F_SECURE_COMMERCIAL

#endif                          /* F_SECURE_COMMERCIAL */
            fprintf(stderr, "sshd version %s [%s]\n", SSH_VERSION, HOSTTYPE);
            fprintf(stderr, "Usage: %s [options]\n", av0);
            fprintf(stderr, "Options:\n");
            fprintf(stderr, "  -f file    Configuration file (default %s/sshd_config)\n", ETCDIR);
            fprintf(stderr, "  -d         Debugging mode\n");
            fprintf(stderr, "  -i         Started from inetd\n");
            fprintf(stderr, "  -q         Quiet (no logging)\n");
            fprintf(stderr, "  -a addr    Bind to the specified address (default: all)\n");
            fprintf(stderr, "  -p port    Listen on the specified port (default: 22)\n");
            fprintf(stderr, "  -k seconds Regenerate server key every this many seconds (default: 3600)\n");
            fprintf(stderr, "  -g seconds Grace period for authentication (default: 300)\n");
            fprintf(stderr, "  -b bits    Size of server RSA key (default: 768 bits)\n");
            fprintf(stderr, "  -h file    File from which to read host key (default: %s)\n", HOST_KEY_FILE);
            fprintf(stderr, "  -V str     Remote version string already read from the socket\n");
            exit(1);
        }
    }

    /* Read server configuration options from the configuration file. */
    read_server_config(&options, config_file_name);

    /* Fill in default values for those options not explicitly set. */
    fill_default_server_options(&options);

    /* Check certain values for sanity. */
    if (options.server_key_bits < 512 || options.server_key_bits > 32768) {
        fprintf(stderr, "fatal: Bad server key size.\n");
        exit(1);
    }
    if (options.port < 1 || options.port > 65535) {
        fprintf(stderr, "fatal: Bad port number.\n");
        exit(1);
    }
    if (options.umask != -1) {
        umask(options.umask);
    }

    /* Check that there are no remaining arguments. */
    if (optind < ac) {
        fprintf(stderr, "fatal: Extra argument %.100s.\n", av[optind]);
        exit(1);
    }

    /* Initialize the log (it is reinitialized below in case we forked). */
    log_init(av0, debug_flag && !inetd_flag, debug_flag || options.fascist_logging, options.quiet_mode, options.log_facility);

    debug("sshd version %.100s [%.100s]", SSH_VERSION, HOSTTYPE);

    /* Load the host key.  It must have empty passphrase. */
    done = load_private_key(geteuid(), options.host_key_file, "", &sensitive_data.host_key, &comment);

    if (!done) {
        if (debug_flag) {
            fprintf(stderr, "Could not load host key: %.200s\n", options.host_key_file);
            fprintf(stderr, "fatal: Please check that you have sufficient permissions and the file exists.\n");
        } else {
            log_init(av0, !inetd_flag, 1, 0, options.log_facility);
            error("fatal: Could not load host key: %.200s.  Check path and permissions.", options.host_key_file);
        }
        exit(1);
    }
    xfree(comment);

    /* If not in debugging mode, and not started from inetd, disconnect from
       the controlling terminal, and fork.  The original process exits. */
    if (!debug_flag && !inetd_flag)
#ifdef HAVE_DAEMON
        if (daemon(0, 0) < 0)
            error("daemon: %.100s", strerror(errno));
    chdir(BBSHOME);
#else                           /* HAVE_DAEMON */
    {
#ifdef TIOCNOTTY
        int fd;
#endif                          /* TIOCNOTTY */

        /* Fork, and have the parent exit.  The child becomes the server. */
        if (fork())
            exit(0);

        /* Redirect stdin, stdout, and stderr to /dev/null. */
        freopen("/dev/null", "r", stdin);
        freopen("/dev/null", "w", stdout);
        freopen("/dev/null", "w", stderr);

        /* Disconnect from the controlling tty. */
#ifdef TIOCNOTTY
        fd = open("/dev/tty", O_RDWR | O_NOCTTY);
        if (fd >= 0) {
            (void) ioctl(fd, TIOCNOTTY, NULL);
            close(fd);
        }
#endif                          /* TIOCNOTTY */
#ifdef HAVE_SETSID
#ifdef ultrix
        setpgrp(0, 0);
#else                           /* ultrix */
        if (setsid() < 0)
            error("setsid: %.100s", strerror(errno));
#endif
#endif                          /* HAVE_SETSID */
    }
#endif                          /* HAVE_DAEMON */

    /* Reinitialize the log (because of the fork above). */
    log_init(av0, debug_flag && !inetd_flag, debug_flag || options.fascist_logging, options.quiet_mode, options.log_facility);

    /* Check that server and host key lengths differ sufficiently.  This is
       necessary to make double encryption work with rsaref.  Oh, I hate
       software patents. */
    if (options.server_key_bits > sensitive_data.host_key.bits - SSH_KEY_BITS_RESERVED && options.server_key_bits < sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED) {
        options.server_key_bits = sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED;
        debug("Forcing server key to %d bits to make it differ from host key.", options.server_key_bits);
    }

    /* Initialize memory allocation so that any freed MP_INT data will be
       zeroed. */
    rsa_set_mp_memory_allocation();

    /* Do not display messages to stdout in RSA code. */
    rsa_set_verbose(debug_flag);

    /* Initialize the random number generator. */
    debug("Initializing random number generator; seed file %.200s", options.random_seed_file);
    random_initialize(&sensitive_data.random_state, geteuid(), options.random_seed_file);

    /* Chdir to the root directory so that the current disk can be unmounted
       if desired. */

    idle_timeout = options.idle_timeout;

    /* Start listening for a socket, unless started from inetd. */
    if (inetd_flag) {
        int s1, s2;

        s1 = dup(0);            /* Make sure descriptors 0, 1, and 2 are in use. */
        s2 = dup(s1);
        sock_in = dup(0);
        sock_out = dup(1);
        /* We intentionally do not close the descriptors 0, 1, and 2 as our
           code for setting the descriptors won\'t work if ttyfd happens to
           be one of those. */
        debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);

        /* Generate an rsa key. */
        log_msg("Generating %d bit RSA key.", options.server_key_bits);
        rsa_generate_key(&sensitive_data.private_key, &public_key, &sensitive_data.random_state, options.server_key_bits);
        random_save(&sensitive_data.random_state, geteuid(), options.random_seed_file);
        log_msg("RSA key generation complete.");
    } else {
        /* Create socket for listening. */
#ifdef HAVE_IPV6_SMTH
        listen_sock = socket(AF_INET6, SOCK_STREAM, 0);
#else       
        listen_sock = socket(AF_INET, SOCK_STREAM, 0);
#endif
        if (listen_sock < 0)
            fatal("socket: %.100s", strerror(errno));

        /* Set socket options.  We try to make the port reusable and have it
           close as fast as possible without waiting in unnecessary wait states
           on close. */
        setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
#if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
        linger.l_onoff = 1;
        linger.l_linger = 15;
        setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
#endif                          /* SO_LINGER */

        /* Initialize the socket address. */
        memset(&sin, 0, sizeof(sin));
#ifdef HAVE_IPV6_SMTH
        sin.sin6_family = AF_INET6;
        if ( inet_pton(AF_INET6, addr, &(sin.sin6_addr)) <= 0 )
            sin.sin6_addr = in6addr_any;
        sin.sin6_port = htons(options.port);
#else
        sin.sin_family = AF_INET;
        if ( inet_pton(AF_INET, addr, &(sin.sin_addr)) <= 0 )
            sin.sin_addr.s_addr = htonl(INADDR_ANY);
        sin.sin_port = htons(options.port);
#endif
        /* Bind the socket to the desired port. */
        if (bind(listen_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
            error("bind: %.100s", strerror(errno));
            shutdown(listen_sock, 2);
            close(listen_sock);
            fatal("Bind to port %d failed: %.200s.", options.port, strerror(errno));
        }
        /* COMMAN : setuid to bbs */

        if(setgid(BBSGID)==-1)
            exit(8);
        if(setuid(BBSUID)==-1)
            exit(8);

#if 0 /* etnlegend, 2006.10.31 ... */
        if (!debug_flag) {
            /* Record our pid in /etc/sshd_pid to make it easier to kill the
               correct sshd.  We don\'t want to do this before the bind above
               because the bind will fail if there already is a daemon, and this
               will overwrite any old pid in the file. */
            f = fopen(options.pid_file, "w");
            if (f) {
                fprintf(f, "%u\n", (unsigned int) getpid());
                fclose(f);
            }
        }
#endif

        /* Start listening on the port. */
        log_msg("Server listening on port %d.", options.port);
        if (listen(listen_sock, 5) < 0)
            fatal("listen: %.100s", strerror(errno));

        /* Generate an rsa key. */
        log_msg("Generating %d bit RSA key.", options.server_key_bits);
        rsa_generate_key(&sensitive_data.private_key, &public_key, &sensitive_data.random_state, options.server_key_bits);
        random_save(&sensitive_data.random_state, geteuid(), options.random_seed_file);
        log_msg("RSA key generation complete.");

        /* Schedule server key regeneration alarm. */
        signal(SIGALRM, key_regeneration_alarm);
        alarm(options.key_regeneration_time);

        /* Arrange to restart on SIGHUP.  The handler needs listen_sock. */
        signal(SIGHUP, sighup_handler);
        signal(SIGTERM, sigterm_handler);
        signal(SIGQUIT, sigterm_handler);

        /* AIX sends SIGDANGER when memory runs low.  The default action is
           to terminate the process.  This sometimes makes it difficult to
           log in and fix the problem. */

#ifdef SIGDANGER
        signal(SIGDANGER, sigdanger_handler);
#endif                          /* SIGDANGER */

        /* Arrange SIGCHLD to be caught. */
        signal(SIGCHLD, main_sigchld_handler);


        if(!debug_flag){
            if(!addr[0])
                sprintf(buf,"var/sshbbsd.%d.pid",options.port);
            else
                sprintf(buf,"var/sshbbsd.%d_%s.pid",options.port,addr);
            if((f=fopen(buf,"w"))){
                fprintf(f,"%d\n",(int)getpid());
                fclose(f);
            }
        }

        /* Stay listening for connections until the system crashes or the
           daemon is killed with a signal. */
        for (;;) {
            if (received_sighup)
                sighup_restart();

            /* Wait in select until there is a connection. */
            FD_ZERO(&fdset);
            FD_SET(listen_sock, &fdset);
            ret = select(listen_sock + 1, &fdset, NULL, NULL, NULL);
            if (ret < 0 || !FD_ISSET(listen_sock, &fdset)) {
                if (errno == EINTR)
                    continue;
                error("select: %.100s", strerror(errno));
                continue;
            }

            aux = sizeof(sin);
            newsock = accept(listen_sock, (struct sockaddr *) &sin, &aux);
            if (newsock < 0) {
                if (errno == EINTR)
                    continue;
                error("accept: %.100s", strerror(errno));
                continue;
            }

            /* Got connection.  Fork a child to handle it, unless we are in
               debugging mode. */
            if (debug_flag) {
                /* In debugging mode.  Close the listening socket, and start
                   processing the connection without forking. */
                debug("Server will not fork when running in debugging mode.");
                close(listen_sock);
                sock_in = newsock;
                sock_out = newsock;
                pid = getpid();
#ifdef LIBWRAP
                {
                    struct request_info req;

                    signal(SIGCHLD, SIG_DFL);

                    request_init(&req, RQ_DAEMON, av0, RQ_FILE, newsock, NULL);
                    fromhost(&req);
                    if (!hosts_access(&req))
                        refuse(&req);
                    syslog(allow_severity, "connect from %s", eval_client(&req));
                }
#endif                          /* LIBWRAP */
                break;
            } else {
#ifdef CHECK_IP_LINK
#ifdef HAVE_IPV6_SMTH
                if (check_IP_lists(sin.sin6_addr)==0)
#else
                if (check_IP_lists(sin.sin_addr.s_addr)==0) 
#endif
#endif
                /* Normal production daemon.  Fork, and have the child process
                   the connection.  The parent continues listening. */
                if ((pid = fork()) == 0) {
                    /* Child.  Close the listening socket, and start using
                       the accepted socket.  Reinitialize logging (since our
                       pid has changed).  We break out of the loop to handle
                       the connection. */
                    close(listen_sock);
                    sock_in = newsock;
                    sock_out = newsock;
#ifdef LIBWRAP
                    {
                        struct request_info req;

                        signal(SIGCHLD, SIG_DFL);

                        request_init(&req, RQ_DAEMON, av0, RQ_FILE, newsock, NULL);
                        fromhost(&req);
                        if (!hosts_access(&req))
                            refuse(&req);
                        syslog(allow_severity, "connect from %s", eval_client(&req));
                    }
#endif                          /* LIBWRAP */

                    log_init(av0, debug_flag && !inetd_flag, options.fascist_logging || debug_flag, options.quiet_mode, options.log_facility);
                    break;
                }
            }

            /* Parent.  Stay in the loop. */
            if (pid < 0)
                error("fork: %.100s", strerror(errno));
            else
                debug("Forked child %d.", pid);

            /* Mark that the key has been used (it was "given" to the child). */
            key_used = 1;

            random_acquire_light_environmental_noise(&sensitive_data.random_state);

            /* Close the new socket (the child is now taking care of it). */
            close(newsock);
        }
    }

    /* This is the child processing a new connection. */

    /* Disable the key regeneration alarm.  We will not regenerate the key
       since we are no longer in a position to give it to anyone.  We will
       not restart on SIGHUP since it no longer makes sense. */
    alarm(0);
    signal(SIGALRM, SIG_DFL);
    signal(SIGHUP, SIG_DFL);
    signal(SIGTERM, SIG_DFL);
    signal(SIGQUIT, SIG_DFL);
    signal(SIGCHLD, SIG_DFL);

    /* Set socket options for the connection.  We want the socket to close
       as fast as possible without waiting for anything.  If the connection
       is not a socket, these will do nothing. */
    /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
#if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
    linger.l_onoff = 1;
    linger.l_linger = 15;
    setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
#endif                          /* SO_LINGER */

    /* Register our connection.  This turns encryption off because we do not
       have a key. */
    packet_set_connection(sock_in, sock_out, &sensitive_data.random_state);

    /* Log the connection. */
    log_msg("Connection from %.100s port %d", get_remote_ipaddr(), get_remote_port());

    /* Check whether logins are denied from this host. */
    {
        const char *hostname = get_canonical_hostname();
        const char *ipaddr = get_remote_ipaddr();
        int i;

        if (options.num_deny_hosts > 0) {
            for (i = 0; i < options.num_deny_hosts; i++)
                if (match_host(hostname, ipaddr, options.deny_hosts[i]))
                    perm_denied = 1;
        }
        if ((!perm_denied) && options.num_allow_hosts > 0) {
            for (i = 0; i < options.num_allow_hosts; i++)
                if (match_host(hostname, ipaddr, options.allow_hosts[i]))
                    break;
            if (i >= options.num_allow_hosts)
                perm_denied = 1;
        }
        if (perm_denied && options.silent_deny) {
            close(sock_in);
            close(sock_out);
            exit(0);
        }
    }

    /* We don't want to listen forever unless the other side successfully
       authenticates itself.  So we set up an alarm which is cleared after
       successful authentication.  A limit of zero indicates no limit.
       Note that we don't set the alarm in debugging mode; it is just annoying
       to have the server exit just when you are about to discover the bug. */
    signal(SIGALRM, grace_alarm_handler);
    if (!debug_flag)
        alarm(options.login_grace_time);


    if (ssh_remote_version_string == NULL) {
        /* Send our protocol version identification. */
        snprintf(buf, sizeof(buf), "SSH-%d.%d-%.50s", PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
        strcat(buf, "\n");
        if (write(sock_out, buf, strlen(buf)) != strlen(buf))
            fatal_severity(SYSLOG_SEVERITY_INFO, "Could not write ident string.");
    }

    if (ssh_remote_version_string == NULL) {
        /* Read other side\'s version identification. */
        for (i = 0; i < sizeof(buf) - 1; i++) {
            if (read(sock_in, &buf[i], 1) != 1)
                fatal_severity(SYSLOG_SEVERITY_INFO, "Did not receive ident string.");
            if (buf[i] == '\r') {
                buf[i] = '\n';
                buf[i + 1] = 0;
                break;
            }
            if (buf[i] == '\n') {
                /* buf[i] == '\n' */
                buf[i + 1] = 0;
                break;
            }
        }
        buf[sizeof(buf) - 1] = 0;
    } else {
        strncpy(buf, ssh_remote_version_string, sizeof(buf) - 1);
        buf[sizeof(buf) - 1] = 0;
    }

    /* Check that the versions match.  In future this might accept several
       versions and set appropriate flags to handle them. */
    if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) != 3) {
        const char *s = "Protocol mismatch.\n";

        (void) write(sock_out, s, strlen(s));
        close(sock_in);
        close(sock_out);
        fatal_severity(SYSLOG_SEVERITY_INFO, "Bad protocol version identification: %.100s", buf);
    }
    debug("Client protocol version %d.%d; client software version %.100s", remote_major, remote_minor, remote_version);

    switch (check_emulation(remote_major, remote_minor, NULL, NULL)) {
    case EMULATE_MAJOR_VERSION_MISMATCH:
        {
            const char *s = "Protocol major versions differ.\n";

            (void) write(sock_out, s, strlen(s));
            close(sock_in);
            close(sock_out);
            fatal_severity(SYSLOG_SEVERITY_INFO, "Protocol major versions differ: %d vs. %d", PROTOCOL_MAJOR, remote_major);
        }
        break;
    case EMULATE_VERSION_TOO_OLD:
        packet_disconnect("Your ssh version is too old and is no " "longer supported.  Please install a newer version.");
        break;
    case EMULATE_VERSION_NEWER:
        packet_disconnect("This server does not support your " "new ssh version.");
        break;
    case EMULATE_VERSION_OK:
        break;
    default:
        fatal("Unexpected return value from check_emulation.");
    }

    if (perm_denied) {
        const char *hostname = get_canonical_hostname();

        log_msg("Connection from %.200s not allowed.\n", hostname);
        packet_disconnect("Sorry, you are not allowed to connect.");
     /*NOTREACHED*/}

    packet_set_nonblocking();

    /* Handle the connection.   We pass as argument whether the connection
       came from a privileged port. */
    do_connection(get_remote_port() < 1024);

    /* The connection has been terminated. */
    log_msg("Closing connection to %.100s", get_remote_ipaddr());
    packet_close();
    exit(0);
}