void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= AUTH_FAIL_LOG || strcmp(method, "password") == 0) authlog = log; if (authctxt->postponed) authmsg = "Postponed"; else authmsg = authenticated ? "Accepted" : "Failed"; authlog("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "illegal user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); #ifdef WITH_AIXAUTHENTICATE if (authenticated == 0 && strcmp(method, "password") == 0) loginfailed(authctxt->user, get_canonical_hostname(options.verify_reverse_mapping), "ssh"); #endif /* WITH_AIXAUTHENTICATE */ }
void auth_log(Authctxt *authctxt, int authenticated, int partial, const char *method, const char *submethod) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; if (use_privsep && !mm_is_monitor() && !authctxt->postponed) return; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else if (partial) authmsg = "Partial"; else { authmsg = authenticated ? "Accepted" : "Failed"; BLACKLIST_NOTIFY(authenticated ? BLACKLIST_AUTH_OK : BLACKLIST_AUTH_FAIL); } authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s", authmsg, method, submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, authctxt->valid ? "" : "invalid user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), compat20 ? "ssh2" : "ssh1", authctxt->info != NULL ? ": " : "", authctxt->info != NULL ? authctxt->info : ""); free(authctxt->info); authctxt->info = NULL; #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0)) record_failed_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh"); # ifdef WITH_AIXAUTHENTICATE if (authenticated) sys_auth_record_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh", &loginmsg); # endif #endif #ifdef SSH_AUDIT_EVENTS if (authenticated == 0 && !authctxt->postponed) audit_event(audit_classify_auth(method)); #endif }
void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; if (use_privsep && !mm_is_monitor() && !authctxt->postponed) return; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else authmsg = authenticated ? "Accepted" : "Failed"; authlog("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "invalid user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0)) record_failed_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh"); # ifdef WITH_AIXAUTHENTICATE if (authenticated) sys_auth_record_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh", &loginmsg); # endif #endif #ifdef SSH_AUDIT_EVENTS if (authenticated == 0 && !authctxt->postponed) audit_event(audit_classify_auth(method)); #endif #ifdef SECURITY_COUNTS if (strcmp(method, "password") == 0) access__attempted(!authenticated, authctxt->user); #endif }
void auth_maxtries_exceeded(Authctxt *authctxt) { error("maximum authentication attempts exceeded for " "%s%.100s from %.200s port %d %s", authctxt->valid ? "" : "invalid user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), compat20 ? "ssh2" : "ssh1"); packet_disconnect("Too many authentication failures"); /* NOTREACHED */ }
void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= AUTH_FAIL_LOG || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else authmsg = authenticated ? "Accepted" : "Failed"; authlog("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "illegal user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && strcmp(method, "password") == 0) record_failed_login(authctxt->user, "ssh"); #endif #ifdef CONFIG_AMAZON if (strcmp(method, "password") == 0) access__attempted(!authenticated, authctxt->user); #endif }
void server_loop2(Authctxt *authctxt) { fd_set *readset = NULL, *writeset = NULL; int rekeying = 0, max_fd, nalloc = 0; double start_time, total_time; debug("Entering interactive session for SSH2."); start_time = get_current_time(); mysignal(SIGCHLD, sigchld_handler); child_terminated = 0; connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); if (!use_privsep) { signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); signal(SIGQUIT, sigterm_handler); } notify_setup(); max_fd = MAX(connection_in, connection_out); max_fd = MAX(max_fd, notify_pipe[0]); server_init_dispatch(); for (;;) { process_buffered_input_packets(); rekeying = (xxx_kex != NULL && !xxx_kex->done); if (!rekeying && packet_not_very_much_data_to_write()) channel_output_poll(); wait_until_can_do_something(&readset, &writeset, &max_fd, &nalloc, 0); if (received_sigterm) { logit("Exiting on signal %d", received_sigterm); /* Clean up sessions, utmp, etc. */ cleanup_exit(255); } collect_children(); if (!rekeying) { channel_after_select(readset, writeset); if (packet_need_rekeying()) { debug("need rekeying"); xxx_kex->done = 0; kex_send_kexinit(xxx_kex); } } process_input(readset); if (connection_closed) break; process_output(writeset); } collect_children(); if (readset) xfree(readset); if (writeset) xfree(writeset); /* free all channels, no more reads and writes */ channel_free_all(); /* free remaining sessions, e.g. remove wtmp entries */ session_destroy_all(NULL); total_time = get_current_time() - start_time; logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f", get_remote_ipaddr(), get_remote_port(), stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, fdout_bytes / total_time); }
static void kex_choose_conf(Kex *kex) { Newkeys *newkeys; char **my, **peer; char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need; int first_kex_follows, type; int log_flag = 0; int auth_flag; auth_flag = packet_authentication_state(); debug ("AUTH STATE IS %d", auth_flag); my = kex_buf2prop(&kex->my, NULL); peer = kex_buf2prop(&kex->peer, &first_kex_follows); if (kex->server) { cprop=peer; sprop=my; } else { cprop=my; sprop=peer; } /* Check whether server offers roaming */ if (!kex->server) { char *roaming; roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); if (roaming) { kex->roaming = 1; xfree(roaming); } } /* Algorithm Negotiation */ for (mode = 0; mode < MODE_MAX; mode++) { newkeys = xcalloc(1, sizeof(*newkeys)); kex->newkeys[mode] = newkeys; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); if (strcmp(newkeys->enc.name, "none") == 0) { debug("Requesting NONE. Authflag is %d", auth_flag); if (auth_flag == 1) { debug("None requested post authentication."); } else { fatal("Pre-authentication none cipher requests are not allowed."); } } debug("kex: %s %s %s %s", ctos ? "client->server" : "server->client", newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); /* client starts withctos = 0 && log flag = 0 and no log*/ /* 2nd client pass ctos=1 and flag = 1 so no log*/ /* server starts with ctos =1 && log_flag = 0 so log */ /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ /* -cjr*/ if (ctos && !log_flag) { logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", get_remote_ipaddr(), get_remote_port(), newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); } log_flag = 1; } choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; if (need < newkeys->enc.key_len) need = newkeys->enc.key_len; if (need < newkeys->enc.block_size) need = newkeys->enc.block_size; if (need < newkeys->mac.key_len) need = newkeys->mac.key_len; } /* XXX need runden? */ kex->we_need = need; /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer) && !(datafellows & SSH_BUG_FIRSTKEX)) { type = packet_read(); debug2("skipping next packet (type %u)", type); } kex_prop_free(my); kex_prop_free(peer); }
static int kex_choose_conf(struct ssh *ssh) { struct kex *kex = ssh->kex; struct newkeys *newkeys; char **my = NULL, **peer = NULL; char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; int log_flag = 0; int r, first_kex_follows; if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 || (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) goto out; if (kex->server) { cprop=peer; sprop=my; } else { cprop=my; sprop=peer; } /* Check whether server offers roaming */ if (!kex->server) { char *roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); if (roaming) { kex->roaming = 1; free(roaming); } } /* Algorithm Negotiation */ for (mode = 0; mode < MODE_MAX; mode++) { if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } kex->newkeys[mode] = newkeys; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; if ((r = choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; goto out; } authlen = cipher_authlen(newkeys->enc.cipher); /* ignore mac for authenticated encryption */ if (authlen == 0 && (r = choose_mac(ssh, &newkeys->mac, cprop[nmac], sprop[nmac])) != 0) { kex->failed_choice = peer[nmac]; peer[nmac] = NULL; goto out; } if ((r = choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; goto out; } debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name); if (strcmp(newkeys->enc.name, "none") == 0) { int auth_flag; auth_flag = ssh_packet_authentication_state(); debug("Requesting NONE. Authflag is %d", auth_flag); if (auth_flag == 1) { debug("None requested post authentication."); } else { fatal("Pre-authentication none cipher requests are not allowed."); } } debug("kex: %s %s %s %s", ctos ? "client->server" : "server->client", newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "<implicit>", newkeys->comp.name); /* client starts withctos = 0 && log flag = 0 and no log*/ /* 2nd client pass ctos=1 and flag = 1 so no log*/ /* server starts with ctos =1 && log_flag = 0 so log */ /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/ /* -cjr*/ if (ctos && !log_flag) { logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s", get_remote_ipaddr(), get_remote_port(), newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); } log_flag = 1; } if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_KEX_ALGS]; peer[PROPOSAL_KEX_ALGS] = NULL; goto out; } if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS]; peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL; goto out; } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; need = MAX(need, newkeys->enc.key_len); need = MAX(need, newkeys->enc.block_size); need = MAX(need, newkeys->enc.iv_len); need = MAX(need, newkeys->mac.key_len); dh_need = MAX(dh_need, cipher_seclen(newkeys->enc.cipher)); dh_need = MAX(dh_need, newkeys->enc.block_size); dh_need = MAX(dh_need, newkeys->enc.iv_len); dh_need = MAX(dh_need, newkeys->mac.key_len); } /* XXX need runden? */ kex->we_need = need; kex->dh_need = dh_need; /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer) && !(ssh->compat & SSH_BUG_FIRSTKEX)) ssh->dispatch_skip_packets = 1; r = 0; out: kex_prop_free(my); kex_prop_free(peer); return r; }
/*ARGSUSED*/ static void input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; char *user, *service, *method, *style = NULL; int authenticated = 0; #ifdef HAVE_LOGIN_CAP login_cap_t *lc; const char *from_host, *from_ip; from_host = get_canonical_hostname(options.use_dns); from_ip = get_remote_ipaddr(); #endif if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); user = packet_get_cstring(NULL); service = packet_get_cstring(NULL); method = packet_get_cstring(NULL); debug("userauth-request for user %s service %s method %s", user, service, method); if (!log_flag) { logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", get_remote_ipaddr(), get_remote_port(), user); log_flag = 1; } debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); if ((style = strchr(user, ':')) != NULL) *style++ = 0; if (authctxt->attempt++ == 0) { /* setup auth context */ authctxt->pw = PRIVSEP(getpwnamallow(user)); authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2("input_userauth_request: setting up authctxt for %s", user); } else { logit("input_userauth_request: invalid user %s", user); authctxt->pw = fakepw(); #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_INVALID_USER)); #endif } #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(authctxt)); #endif setproctitle("%s%s", authctxt->valid ? user : "******", use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; if (use_privsep) mm_inform_authserv(service, style); userauth_banner(); if (auth2_setup_methods_lists(authctxt) != 0) packet_disconnect("no authentication methods enabled"); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { packet_disconnect("Change of username or service not allowed: " "(%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } #ifdef HAVE_LOGIN_CAP if (authctxt->pw != NULL) { lc = login_getpwclass(authctxt->pw); if (lc == NULL) lc = login_getclassbyname(NULL, authctxt->pw); if (!auth_hostok(lc, from_host, from_ip)) { logit("Denied connection for %.200s from %.200s [%.200s].", authctxt->pw->pw_name, from_host, from_ip); packet_disconnect("Sorry, you are not allowed to connect."); } if (!auth_timeok(lc, time(NULL))) { logit("LOGIN %.200s REFUSED (TIME) FROM %.200s", authctxt->pw->pw_name, from_host); packet_disconnect("Logins not available right now."); } login_close(lc); lc = NULL; } #endif /* HAVE_LOGIN_CAP */ /* reset state */ auth2_challenge_stop(authctxt); #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif authctxt->postponed = 0; authctxt->server_caused_failure = 0; /* try to authenticate user */ m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(authctxt); } userauth_finish(authctxt, authenticated, method, NULL); free(service); free(user); free(method); }
char *ident_username(rfbClientPtr client) { ClientData *cd = (ClientData *) client->clientData; char *str, *newhost, *user = NULL, *newuser = NULL; int len; if (cd) { user = cd->username; } if (!user || *user == '\0') { int n, sock, ok = 0; int block = 0; int refused = 0; /* * need to check to see if the operation will block for * a long time: a firewall may just ignore our packets. */ #if LIBVNCSERVER_HAVE_FORK { pid_t pid, pidw; int rc; if ((pid = fork()) > 0) { usleep(100 * 1000); /* 0.1 sec for quick success or refusal */ pidw = waitpid(pid, &rc, WNOHANG); if (pidw <= 0) { usleep(1500 * 1000); /* 1.5 sec */ pidw = waitpid(pid, &rc, WNOHANG); if (pidw <= 0) { int rc2; rfbLog("ident_username: set block=1 (hung)\n"); block = 1; kill(pid, SIGTERM); usleep(100 * 1000); waitpid(pid, &rc2, WNOHANG); } } if (pidw > 0 && !block) { if (WIFEXITED(rc) && WEXITSTATUS(rc) == 1) { rfbLog("ident_username: set refused=1 (exit)\n"); refused = 1; } } } else if (pid == -1) { ; } else { /* child */ signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); if ((sock = connect_tcp(client->host, 113)) < 0) { exit(1); } else { close(sock); exit(0); } } } #endif if (block || refused) { ; } else if ((sock = connect_tcp(client->host, 113)) < 0) { rfbLog("ident_username: could not connect to ident: %s:%d\n", client->host, 113); } else { char msg[128]; int ret; fd_set rfds; struct timeval tv; int rport = get_remote_port(client->sock); int lport = get_local_port(client->sock); sprintf(msg, "%d, %d\r\n", rport, lport); n = write(sock, msg, strlen(msg)); FD_ZERO(&rfds); FD_SET(sock, &rfds); tv.tv_sec = 3; tv.tv_usec = 0; ret = select(sock+1, &rfds, NULL, NULL, &tv); if (ret > 0) { int i; char *q, *p; for (i=0; i < (int) sizeof(msg); i++) { msg[i] = '\0'; } usleep(250*1000); n = read(sock, msg, 127); close(sock); if (n <= 0) goto badreply; /* 32782 , 6000 : USERID : UNIX :runge */ q = strstr(msg, "USERID"); if (!q) goto badreply; q = strstr(q, ":"); if (!q) goto badreply; q++; q = strstr(q, ":"); if (!q) goto badreply; q++; q = lblanks(q); p = q; while (*p) { if (*p == '\r' || *p == '\n') { *p = '\0'; } p++; } ok = 1; if (strlen(q) > 24) { *(q+24) = '\0'; } newuser = strdup(q); badreply: n = 0; /* avoid syntax error */ } else { close(sock); } } if (! ok || !newuser) { newuser = strdup("unknown-user"); } if (cd) { if (cd->username) { free(cd->username); } cd->username = newuser; } user = newuser; } if (!strcmp(user, "unknown-user") && cd && cd->unixname[0] != '\0') { user = cd->unixname; } if (unixpw && openssl_last_ip && strstr("UNIX:", user) != user) { newhost = ip2host(openssl_last_ip); } else { newhost = ip2host(client->host); } len = strlen(user) + 1 + strlen(newhost) + 1; str = (char *) malloc(len); sprintf(str, "%s@%s", user, newhost); free(newhost); return str; }
/* ============================================================================ Routine to create the PeripheralSetup Window and tabs ============================================================================ */ void cb_SocketSetup (Fl_Widget* w, void*) { Fl_Box* b; int port_num, enabled, telnet; // Get socket interface preferences virtualt_prefs.get("SocketPort", port_num, get_remote_port()); telnet = get_remote_telnet(); enabled = get_remote_enabled(); // Create Peripheral Setup window gsdw = new Fl_Window(300, 260, "Socket Configuration"); gsdw->callback(cb_sockdlg_win); /* Create enable checkbox */ sockdlg_ctrl.pEnable = new Fl_Check_Button(20, 20, 190, 20, "Enable Socket Interface"); sockdlg_ctrl.pEnable->callback(cb_sockdlg_enable); sockdlg_ctrl.pEnable->value(enabled); /* Create input field for for port number */ b = new Fl_Box(50, 50, 70, 20, "Port Number"); b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); sockdlg_ctrl.pPortNumber = new Fl_Input(160, 50, 60, 20, ""); sockdlg_ctrl.pPortNumber->align(FL_ALIGN_LEFT); sprintf(sockdlg_ctrl.sPortNumber, "%d", port_num); sockdlg_ctrl.pPortNumber->value(sockdlg_ctrl.sPortNumber); // Create checkbox for telnet mode sockdlg_ctrl.pTelnet = new Fl_Check_Button(50, 80, 200, 20, "Telnet Mode (std port is 23)"); sockdlg_ctrl.pTelnet->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); sockdlg_ctrl.pTelnet->value(telnet); // Deactivate port number and telnet mode if socket interface inactive if (!enabled) { sockdlg_ctrl.pPortNumber->deactivate(); sockdlg_ctrl.pTelnet->deactivate(); } b = new Fl_Box(20, 130, 120, 20, "Socket Port Status"); b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); sockdlg_ctrl.pStatus = new Fl_Box(50, 160, 200, 20, ""); sockdlg_ctrl.pStatus->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); update_port_status(); // Cancel button { Fl_Button* o = new Fl_Button(40, 200, 60, 30, "Cancel"); o->callback((Fl_Callback*) cb_sockdlg_cancel); } // Apply button sockdlg_ctrl.pApply = new Fl_Button(120, 200, 60, 30, "Apply"); sockdlg_ctrl.pApply->callback((Fl_Callback*) cb_sockdlg_apply); // OK button { Fl_Return_Button* o = new Fl_Return_Button(200, 200, 60, 30, "OK"); o->callback((Fl_Callback*)cb_sockdlg_OK); } gsdw->show(); }
void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else authmsg = authenticated ? "Accepted" : "Failed"; authlog("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "invalid user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0)) record_failed_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh"); #endif #ifdef SSH_AUDIT_EVENTS if (authenticated == 0 && !authctxt->postponed) { ssh_audit_event_t event; debug3("audit failed auth attempt, method %s euid %d", method, (int)geteuid()); /* * Because the auth loop is used in both monitor and slave, * we must be careful to send each event only once and with * enough privs to write the event. */ event = audit_classify_auth(method); switch(event) { case SSH_AUTH_FAIL_NONE: case SSH_AUTH_FAIL_PASSWD: case SSH_AUTH_FAIL_KBDINT: if (geteuid() == 0) audit_event(event); break; case SSH_AUTH_FAIL_PUBKEY: case SSH_AUTH_FAIL_HOSTBASED: case SSH_AUTH_FAIL_GSSAPI: /* * This is required to handle the case where privsep * is enabled but it's root logging in, since * use_privsep won't be cleared until after a * successful login. */ if (geteuid() == 0) audit_event(event); else PRIVSEP(audit_event(event)); break; default: error("unknown authentication audit event %d", event); } } #endif }
void auth_log(Authctxt *authctxt, int authenticated, int partial, const char *method, const char *submethod, const char *info) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; if (use_privsep && !mm_is_monitor() && !authctxt->postponed) return; /* Raise logging level */ if (authenticated == 1 || !authctxt->valid || authctxt->failures >= options.max_authtries / 2 || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else if (partial) authmsg = "Partial"; else authmsg = authenticated ? "Accepted" : "Failed"; authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", authmsg, method, submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, authctxt->valid ? "" : "invalid user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); #ifdef NERSC_MOD char* t1buf = encode_string(authctxt->user, strlen(authctxt->user) ); char* t2buf = encode_string(method, strlen(method) ); char* t3buf = encode_string(authmsg, strlen(authmsg) ); s_audit("auth_info_3", "count=%i uristring=%s uristring=%s uristring=%s addr=%.200s port=%d/tcp addr=%s port=%s/tcp", client_session_id, t3buf, t1buf, t2buf, get_remote_ipaddr(), get_remote_port(), n_ntop, n_port); free(t1buf); free(t2buf); free(t3buf); #endif #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0)) record_failed_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh"); # ifdef WITH_AIXAUTHENTICATE if (authenticated) sys_auth_record_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh", &loginmsg); # endif #endif #ifdef SSH_AUDIT_EVENTS if (authenticated == 0 && !authctxt->postponed) audit_event(audit_classify_auth(method)); #endif }
/* * Main program for the daemon. */ int main(int ac, char **av) { extern char *optarg; extern int optind; int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; pid_t pid; socklen_t fromlen; fd_set *fdset; struct sockaddr_storage from; const char *remote_ip; int remote_port; FILE *f; struct linger linger; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; int listen_sock, maxfd; int startup_p[2]; int startups = 0; Authctxt *authctxt; Key *key; int ret, key_used = 0; #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = get_progname(av[0]); init_rng(); /* Save argv. */ saved_argc = ac; saved_argv = av; /* Initialize configuration options to their default values. */ initialize_server_options(&options); /* Parse command-line arguments. */ while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46:S")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; break; case '6': IPv4or6 = AF_INET6; break; case 'f': config_file_name = optarg; break; case 'd': if (0 == debug_flag) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { options.log_level++; } else { fprintf(stderr, "Too high debugging level.\n"); exit(1); } break; case 'D': no_daemon_flag = 1; break; case 'e': log_stderr = 1; break; case 'i': inetd_flag = 1; break; case 'Q': /* ignored */ break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': options.server_key_bits = atoi(optarg); break; case 'p': options.ports_from_cmdline = 1; if (options.num_ports >= MAX_PORTS) { fprintf(stderr, "too many ports.\n"); exit(1); } options.ports[options.num_ports++] = a2port(optarg); if (options.ports[options.num_ports-1] == 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } break; case 'g': if ((options.login_grace_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } break; case 'k': if ((options.key_regeneration_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid key regeneration interval.\n"); exit(1); } break; case 'h': if (options.num_host_key_files >= MAX_HOSTKEYS) { fprintf(stderr, "too many host keys.\n"); exit(1); } options.host_key_files[options.num_host_key_files++] = optarg; break; case 'V': client_version_string = optarg; /* only makes sense with inetd_flag, i.e. no listen() */ inetd_flag = 1; break; case 't': test_flag = 1; break; case 'u': utmp_len = atoi(optarg); break; case 'o': if (process_server_config_line(&options, optarg, "command-line", 0) != 0) exit(1); break; case 'S': protocol = IPPROTO_SCTP; break; case '?': default: usage(); break; } } SSLeay_add_all_algorithms(); channel_set_af(IPv4or6); /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd) */ log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, !inetd_flag); #ifdef _CRAY /* Cray can define user privs drop all prives now! * Not needed on PRIV_SU systems! */ drop_cray_privs(); #endif seed_rng(); /* 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 that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); exit(1); } debug("sshd version %.100s", SSH_VERSION); /* load private host keys */ sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_keys[i] = NULL; sensitive_data.server_key = NULL; sensitive_data.ssh1_host_key = NULL; sensitive_data.have_ssh1_key = 0; sensitive_data.have_ssh2_key = 0; for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); sensitive_data.host_keys[i] = key; if (key == NULL) { error("Could not load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; continue; } switch (key->type) { case KEY_RSA1: sensitive_data.ssh1_host_key = key; sensitive_data.have_ssh1_key = 1; break; case KEY_RSA: case KEY_DSA: sensitive_data.have_ssh2_key = 1; break; } debug("private host key: #%d type %d %s", i, key->type, key_type(key)); } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { log("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; } if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { log("Disabling protocol version 2. Could not load host key"); options.protocol &= ~SSH_PROTO_2; } if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { log("sshd: no hostkeys available -- exiting."); exit(1); } /* Check certain values for sanity. */ if (options.protocol & SSH_PROTO_1) { if (options.server_key_bits < 512 || options.server_key_bits > 32768) { fprintf(stderr, "Bad server key size.\n"); exit(1); } /* * Check that server and host key lengths differ sufficiently. This * is necessary to make double encryption work with rsaref. Oh, I * hate software patents. I dont know if this can go? Niels */ if (options.server_key_bits > BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - SSH_KEY_BITS_RESERVED && options.server_key_bits < BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { options.server_key_bits = BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED; debug("Forcing server key to %d bits to make it differ from host key.", options.server_key_bits); } } if (use_privsep) { struct passwd *pw; struct stat st; if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || (S_ISDIR(st.st_mode) == 0)) fatal("Missing privilege separation directory: %s", _PATH_PRIVSEP_CHROOT_DIR); if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) fatal("Bad owner or mode for %s", _PATH_PRIVSEP_CHROOT_DIR); } /* Configuration looks good, so exit if in test mode. */ if (test_flag) exit(0); /* * Clear out any supplemental groups we may have inherited. This * prevents inadvertent creation of files with bad modes (in the * portable version at least, it's certainly possible for PAM * to create a file, and we can't control the code in every * module which might be used). */ if (setgroups(0, NULL) < 0) debug("setgroups() failed: %.200s", strerror(errno)); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && !inetd_flag) log_stderr = 1; log_init(__progname, options.log_level, options.log_facility, log_stderr); /* * 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 || no_daemon_flag)) { #ifdef TIOCNOTTY int fd; #endif /* TIOCNOTTY */ if (daemon(0, 0) < 0) fatal("daemon() failed: %.200s", strerror(errno)); /* Disconnect from the controlling tty. */ #ifdef TIOCNOTTY fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); if (fd >= 0) { (void) ioctl(fd, TIOCNOTTY, NULL); close(fd); } #endif /* TIOCNOTTY */ } /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); /* Initialize the random number generator. */ arc4random_stir(); /* Chdir to the root directory so that the current disk can be unmounted if desired. */ chdir("/"); /* ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); /* Start listening for a socket, unless started from inetd. */ if (inetd_flag) { int s1; s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ dup(s1); sock_in = dup(0); sock_out = dup(1); startup_pipe = -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); if (options.protocol & SSH_PROTO_1) generate_ephemeral_server_key(); } else { for (ai = options.listen_addrs; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; if (num_listen_socks >= MAX_LISTEN_SOCKS) fatal("Too many listen sockets. " "Enlarge MAX_LISTEN_SOCKS"); if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error("getnameinfo failed"); continue; } /* Create socket for listening. */ listen_sock = socket(ai->ai_family, SOCK_STREAM, protocol); if (listen_sock < 0) { /* kernel may not support ipv6 */ verbose("socket: %.100s", strerror(errno)); continue; } if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { error("listen_sock O_NONBLOCK: %s", strerror(errno)); close(listen_sock); continue; } /* * 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, &on, sizeof(on)); linger.l_onoff = 1; linger.l_linger = 5; setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); debug("Bind to port %s on %s.", strport, ntop); /* Bind the socket to the desired port. */ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { if (!ai->ai_next) error("Bind to port %s on %s failed: %.200s.", strport, ntop, strerror(errno)); close(listen_sock); continue; } listen_socks[num_listen_socks] = listen_sock; num_listen_socks++; /* Start listening on the port. */ log("Server listening on %s port %s.", ntop, strport); if (listen(listen_sock, 5) < 0) fatal("listen: %.100s", strerror(errno)); } freeaddrinfo(options.listen_addrs); if (!num_listen_socks) fatal("Cannot bind any address."); if (options.protocol & SSH_PROTO_1) generate_ephemeral_server_key(); /* * Arrange to restart on SIGHUP. The handler needs * listen_sock. */ signal(SIGHUP, sighup_handler); signal(SIGTERM, sigterm_handler); signal(SIGQUIT, sigterm_handler); /* Arrange SIGCHLD to be caught. */ signal(SIGCHLD, main_sigchld_handler); /* Write out the pid file after the sigterm handler is setup */ if (!debug_flag) { /* * Record our pid in /var/run/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, "wb"); if (f) { fprintf(f, "%ld\n", (long) getpid()); fclose(f); } } /* setup fd set for listen */ fdset = NULL; maxfd = 0; for (i = 0; i < num_listen_socks; i++) if (listen_socks[i] > maxfd) maxfd = listen_socks[i]; /* pipes connected to unauthenticated childs */ startup_pipes = xmalloc(options.max_startups * sizeof(int)); for (i = 0; i < options.max_startups; i++) startup_pipes[i] = -1; /* * Stay listening for connections until the system crashes or * the daemon is killed with a signal. */ for (;;) { if (received_sighup) sighup_restart(); if (fdset != NULL) xfree(fdset); fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); fdset = (fd_set *)xmalloc(fdsetsz); memset(fdset, 0, fdsetsz); for (i = 0; i < num_listen_socks; i++) FD_SET(listen_socks[i], fdset); for (i = 0; i < options.max_startups; i++) if (startup_pipes[i] != -1) FD_SET(startup_pipes[i], fdset); /* Wait in select until there is a connection. */ ret = select(maxfd+1, fdset, NULL, NULL, NULL); if (ret < 0 && errno != EINTR) error("select: %.100s", strerror(errno)); if (received_sigterm) { log("Received signal %d; terminating.", (int) received_sigterm); close_listen_socks(); unlink(options.pid_file); exit(255); } if (key_used && key_do_regen) { generate_ephemeral_server_key(); key_used = 0; key_do_regen = 0; } if (ret < 0) continue; for (i = 0; i < options.max_startups; i++) if (startup_pipes[i] != -1 && FD_ISSET(startup_pipes[i], fdset)) { /* * the read end of the pipe is ready * if the child has closed the pipe * after successful authentication * or if the child has died */ close(startup_pipes[i]); startup_pipes[i] = -1; startups--; } for (i = 0; i < num_listen_socks; i++) { if (!FD_ISSET(listen_socks[i], fdset)) continue; fromlen = sizeof(from); newsock = accept(listen_socks[i], (struct sockaddr *)&from, &fromlen); if (newsock < 0) { if (errno != EINTR && errno != EWOULDBLOCK) error("accept: %.100s", strerror(errno)); continue; } if (fcntl(newsock, F_SETFL, 0) < 0) { error("newsock del O_NONBLOCK: %s", strerror(errno)); close(newsock); continue; } if (drop_connection(startups) == 1) { debug("drop connection #%d", startups); close(newsock); continue; } if (pipe(startup_p) == -1) { close(newsock); continue; } for (j = 0; j < options.max_startups; j++) if (startup_pipes[j] == -1) { startup_pipes[j] = startup_p[0]; if (maxfd < startup_p[0]) maxfd = startup_p[0]; startups++; break; } /* * 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_socks(); sock_in = newsock; sock_out = newsock; startup_pipe = -1; pid = getpid(); break; } else { /* * Normal production daemon. Fork, and have * the child process the connection. The * parent continues listening. */ if ((pid = fork()) == 0) { /* * Child. Close the listening and max_startup * sockets. Start using the accepted socket. * Reinitialize logging (since our pid has * changed). We break out of the loop to handle * the connection. */ startup_pipe = startup_p[1]; close_startup_pipes(); close_listen_socks(); sock_in = newsock; sock_out = newsock; log_init(__progname, options.log_level, options.log_facility, log_stderr); break; } } /* Parent. Stay in the loop. */ if (pid < 0) error("fork: %.100s", strerror(errno)); else debug("Forked child %ld.", (long)pid); close(startup_p[1]); /* Mark that the key has been used (it was "given" to the child). */ if ((options.protocol & SSH_PROTO_1) && key_used == 0) { /* Schedule server key regeneration alarm. */ signal(SIGALRM, key_regeneration_alarm); alarm(options.key_regeneration_time); key_used = 1; } arc4random_stir(); /* Close the new socket (the child is now taking care of it). */ close(newsock); } /* child process check (or debug mode) */ if (num_listen_socks < 0) break; } } /* This is the child processing a new connection. */ /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. We don't * want the child to be able to affect the parent. */ #if 0 /* XXX: this breaks Solaris */ if (!debug_flag && !inetd_flag && setsid() < 0) error("setsid: %.100s", strerror(errno)); #endif /* * 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); signal(SIGINT, 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)); */ linger.l_onoff = 1; linger.l_linger = 5; setsockopt(sock_in, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); /* Set keepalives if requested. */ if (options.keepalives && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); /* * Register our connection. This turns encryption off because we do * not have a key. */ packet_set_connection(sock_in, sock_out); remote_port = get_remote_port(); remote_ip = get_remote_ipaddr(); #ifdef LIBWRAP /* Check whether logins are denied from this host. */ { struct request_info req; request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); fromhost(&req); if (!hosts_access(&req)) { debug("Connection refused by tcp wrapper"); refuse(&req); /* NOTREACHED */ fatal("libwrap refuse returns"); } } #endif /* LIBWRAP */ /* Log the connection. */ verbose("Connection from %.500s port %d", remote_ip, remote_port); /* * 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); sshd_exchange_identification(sock_in, sock_out); /* * Check that the connection comes from a privileged port. * Rhosts-Authentication only makes sense from privileged * programs. Of course, if the intruder has root access on his local * machine, he can connect from any port. So do not use these * authentication methods from machines that you do not trust. */ if (options.rhosts_authentication && (remote_port >= IPPORT_RESERVED || remote_port < IPPORT_RESERVED / 2)) { debug("Rhosts Authentication disabled, " "originating port %d not trusted.", remote_port); options.rhosts_authentication = 0; } #if defined(KRB4) && !defined(KRB5) if (!packet_connection_is_ipv4() && options.kerberos_authentication) { debug("Kerberos Authentication disabled, only available for IPv4."); options.kerberos_authentication = 0; } #endif /* KRB4 && !KRB5 */ #ifdef AFS /* If machine has AFS, set process authentication group. */ if (k_hasafs()) { k_setpag(); k_unlog(); } #endif /* AFS */ packet_set_nonblocking(); if (use_privsep) if ((authctxt = privsep_preauth()) != NULL) goto authenticated; /* perform the key exchange */ /* authenticate user and start session */ if (compat20) { do_ssh2_kex(); authctxt = do_authentication2(); } else { do_ssh1_kex(); authctxt = do_authentication(); } /* * If we use privilege separation, the unprivileged child transfers * the current keystate and exits */ if (use_privsep) { mm_send_keystate(pmonitor); exit(0); } authenticated: /* * In privilege separation, we fork another child and prepare * file descriptor passing. */ if (use_privsep) { privsep_postauth(authctxt); /* the monitor process [priv] will not return */ if (!compat20) destroy_sensitive_data(); } /* Perform session preparation. */ do_authenticated(authctxt); /* The connection has been terminated. */ verbose("Closing connection to %.100s", remote_ip); #ifdef USE_PAM finish_pam(); #endif /* USE_PAM */ packet_close(); if (use_privsep) mm_terminate(); exit(0); }
/** * @brief Handle an incoming RTSP connection * * @param loop The event loop where the incoming connection was triggered * @param w The watcher that triggered the incoming connection * @param revents Unused * * This function takes care of all the handling of an incoming RTSP * client connection: * * @li accept the new socket; * * @li checks that there is space for new connections for the current * fork; * * @li creates and sets up the @ref RTSP_Client object. * * The newly created instance is deleted by @ref * client_ev_disconnect_handler. * * @internal This function should be used as callback for an ev_io * listener. */ void rtsp_client_incoming_cb(struct ev_loop *loop, ev_io *w, int revents) { Sock *sock = w->data; feng *srv = sock->data; Sock *client_sock = NULL; ev_io *io; ev_async *async; ev_timer *timer; RTSP_Client *rtsp; client_port_pair *clients=NULL; pid_t pid; if ( (client_sock = Sock_accept(sock, NULL)) == NULL ) return; if (srv->connection_count >= ONE_FORK_MAX_CONNECTION) { Sock_close(client_sock); return; } if(!( clients = new_child_port(srv, get_remote_host(client_sock), get_remote_port(client_sock)))){ Sock_close(client_sock); return; } pid = fork(); if(pid==0){ /*clean the context of parent*/ clients->pid = getpid(); current_client = clients; //free_child_port(clients); feng_ports_cleanup(srv); feng_stop_child_watcher(srv); demuxer_stsw_global_init(); //void fnc_log_change_child(); if(srv->srvconf.log_type == FNC_LOG_FILE){ //child process can't write to parent log file fnc_log_uninit(); } rtsp = g_slice_new0(RTSP_Client); rtsp->sock = client_sock; rtsp->input = g_byte_array_new(); rtsp->out_queue = g_queue_new(); rtsp->srv = srv; rtsp->cached_resource = NULL; srv->connection_count++; client_sock->data = srv; /*install read handler*/ io = &rtsp->ev_io_read; io->data = rtsp; ev_io_init(io, rtsp_read_cb, Sock_fd(client_sock), EV_READ); ev_io_start(srv->loop, io); /* configure the write handler*/ /* to be started/stopped when necessary */ io = &rtsp->ev_io_write; io->data = rtsp; ev_io_init(io, rtsp_write_cb, Sock_fd(client_sock), EV_WRITE); fnc_log(FNC_LOG_INFO, "Incoming RTSP connection accepted on socket: %d\n", Sock_fd(client_sock)); /* install async event handler for destroy */ async = &rtsp->ev_sig_disconnect; async->data = rtsp; ev_async_init(async, client_ev_disconnect_handler); ev_async_start(srv->loop, async); /* configure a check timer, * After play, this timer would be started */ timer = &rtsp->ev_timeout; timer->data = rtsp; ev_init(timer, client_ev_timeout); timer->repeat = STREAM_TIMEOUT; }else if(pid > 0){ Sock_close(client_sock); srv->connection_count++; clients->pid = pid; fnc_log(FNC_LOG_INFO, "The child process (pid:%d) for rtsp connection (%s:%hu) is created\n", pid, clients->host, clients->port); fnc_log(FNC_LOG_INFO, "Connection reached: %d\n", srv->connection_count); add_client_list(clients); return; }else{ Sock_close(client_sock); free_child_port(clients); fnc_log(FNC_LOG_ERR, "fork faild\n"); return; } }
/*ARGSUSED*/ static void input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; char *user, *service, *method, *style = NULL; int authenticated = 0; if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); user = packet_get_cstring(NULL); service = packet_get_cstring(NULL); method = packet_get_cstring(NULL); debug("userauth-request for user %s service %s method %s", user, service, method); if (!log_flag) { logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", get_remote_ipaddr(), get_remote_port(), user); log_flag = 1; } debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); if ((style = strchr(user, ':')) != NULL) *style++ = 0; if (authctxt->attempt++ == 0) { /* setup auth context */ authctxt->pw = PRIVSEP(getpwnamallow(user)); authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2("input_userauth_request: setting up authctxt for %s", user); } else { logit("input_userauth_request: invalid user %s", user); authctxt->pw = fakepw(); #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_INVALID_USER)); #endif } #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(authctxt)); #endif setproctitle("%s%s", authctxt->valid ? user : "******", use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; if (use_privsep) mm_inform_authserv(service, style); userauth_banner(); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { packet_disconnect("Change of username or service not allowed: " "(%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } /* reset state */ auth2_challenge_stop(authctxt); #ifdef JPAKE auth2_jpake_stop(authctxt); #endif #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif authctxt->postponed = 0; /* try to authenticate user */ m = authmethod_lookup(method); if (m != NULL && authctxt->failures < options.max_authtries) { debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(authctxt); } userauth_finish(authctxt, authenticated, method); xfree(service); xfree(user); xfree(method); }
void auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) { void (*authlog) (const char *fmt,...) = verbose; void (*final_authlog) (const char *fmt,...) = logit_notice; char *authmsg; char *gecos = NULL; int is_none_first_failure = 0; if (use_privsep && !mm_is_monitor() && !authctxt->postponed) return; /* * Avoid unhelpful messages about "Failed none", which happen * because the infrastructure always first tries to see if * logging in with an empty password will work. */ if (authenticated == 0 && !(authctxt->postponed) && authctxt->failures == 0 && strcmp(method, "none") == 0) { is_none_first_failure = 1; authlog = debug; final_authlog = debug; } /* Raise logging level */ else if (authenticated == 1 || !authctxt->valid || authctxt->failures >= AUTH_FAIL_LOG || strcmp(method, "password") == 0) authlog = logit; if (authctxt->postponed) authmsg = "Postponed"; else authmsg = authenticated ? "Accepted" : "Failed"; if (authctxt->valid || aaa_log_unknown_usernames_flag) { (*authlog)("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "unknown user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); } else { debug("%s %s for %s%.100s from %.200s port %d%s", authmsg, method, authctxt->valid ? "" : "unknown user ", authctxt->user, get_remote_ipaddr(), get_remote_port(), info); (*authlog)("%s %s for unknown user from %.200s port %d%s", authmsg, method, get_remote_ipaddr(), get_remote_port(), info); } if (!(authctxt->postponed)) { gecos = get_gecos(authctxt->user); if (authenticated) { (*final_authlog)("%s %s%s logged in via%s from %s", authctxt->valid ? "User" : "Unknown user", authctxt->user, gecos ? gecos : "", info, get_remote_ipaddr()); } else { if (authctxt->valid || aaa_log_unknown_usernames_flag) { (*final_authlog)("%s %s%s failed to login via%s from %s", authctxt->valid ? "User" : "Unknown user", authctxt->user, gecos ? gecos : "", info, get_remote_ipaddr()); } else { debug("%s %s%s failed to login via%s from %s", authctxt->valid ? "User" : "Unknown user", authctxt->user, gecos ? gecos : "", info, get_remote_ipaddr()); (*final_authlog)("Unknown user failed to login via%s from %s", info, get_remote_ipaddr()); } } if (gecos) { free(gecos); } } #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && !is_none_first_failure && (strcmp(method, "password") == 0 || strncmp(method, "keyboard-interactive", 20) == 0 || strcmp(method, "challenge-response") == 0)) record_failed_login(authctxt->user, get_canonical_hostname(options.use_dns), "ssh"); #endif }
/* * Main program for the ssh client. */ int main(int ac, char **av) { int i, r, opt, exit_status, use_syslog; char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; struct stat st; struct passwd *pw; int dummy, timeout_ms; extern int optind, optreset; extern char *optarg; struct servent *sp; Forward fwd; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(av[0]); #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ /* Save argv so it isn't clobbered by setproctitle() emulation */ saved_av = xcalloc(ac + 1, sizeof(*saved_av)); for (i = 0; i < ac; i++) saved_av[i] = xstrdup(av[i]); saved_av[i] = NULL; compat_init_setproctitle(ac, av); av = saved_av; #endif /* * Discard other fds that are hanging around. These can cause problem * with backgrounded ssh processes started by ControlPersist. */ closefrom(STDERR_FILENO + 1); /* * Save the original real uid. It will be needed later (uid-swapping * may clobber the real uid). */ original_real_uid = getuid(); original_effective_uid = geteuid(); /* * Use uid-swapping to give up root privileges for the duration of * option processing. We will re-instantiate the rights when we are * ready to create the privileged port, and will permanently drop * them when the port has been created (actually, when the connection * has been made, as we may need to create the port several times). */ PRIV_END; #ifdef HAVE_SETRLIMIT /* If we are installed setuid root be careful to not drop core. */ if (original_real_uid != original_effective_uid) { struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rlim) < 0) fatal("setrlimit failed: %.100s", strerror(errno)); } #endif /* Get user data. */ pw = getpwuid(original_real_uid); if (!pw) { logit("You don't exist, go away!"); exit(255); } /* Take a copy of the returned structure. */ pw = pwcopy(pw); /* * Set our umask to something reasonable, as some files are created * with the default umask. This will make them world-readable but * writable only by the owner, which is ok for all files for which we * don't set the modes explicitly. */ umask(022); /* * Initialize option structure to indicate that no values have been * set. */ initialize_options(&options); /* Parse command-line arguments. */ host = NULL; use_syslog = 0; argv0 = av[0]; again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': options.protocol = SSH_PROTO_1; break; case '2': options.protocol = SSH_PROTO_2; break; case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'n': stdin_null_flag = 1; break; case 'f': fork_after_authentication_flag = 1; stdin_null_flag = 1; break; case 'x': options.forward_x11 = 0; break; case 'X': options.forward_x11 = 1; break; case 'y': use_syslog = 1; break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; break; case 'g': options.gateway_ports = 1; break; case 'O': if (stdio_forward_host != NULL) fatal("Cannot specify multiplexing " "command with -W"); else if (muxclient_command != 0) fatal("Multiplexing command already specified"); if (strcmp(optarg, "check") == 0) muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; else if (strcmp(optarg, "forward") == 0) muxclient_command = SSHMUX_COMMAND_FORWARD; else if (strcmp(optarg, "exit") == 0) muxclient_command = SSHMUX_COMMAND_TERMINATE; else if (strcmp(optarg, "stop") == 0) muxclient_command = SSHMUX_COMMAND_STOP; else if (strcmp(optarg, "cancel") == 0) muxclient_command = SSHMUX_COMMAND_CANCEL_FWD; else fatal("Invalid multiplex command."); break; case 'P': /* deprecated */ options.use_privileged_port = 0; break; case 'a': options.forward_agent = 0; break; case 'A': options.forward_agent = 1; break; case 'k': options.gss_deleg_creds = 0; break; case 'K': options.gss_authentication = 1; options.gss_deleg_creds = 1; break; case 'i': if (stat(optarg, &st) < 0) { fprintf(stderr, "Warning: Identity file %s " "not accessible: %s.\n", optarg, strerror(errno)); break; } if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES) fatal("Too many identity files specified " "(max %d)", SSH_MAX_IDENTITY_FILES); options.identity_files[options.num_identity_files++] = xstrdup(optarg); break; case 'I': #ifdef ENABLE_PKCS11 options.pkcs11_provider = xstrdup(optarg); #else fprintf(stderr, "no support for PKCS#11.\n"); #endif break; case 't': if (options.request_tty == REQUEST_TTY_YES) options.request_tty = REQUEST_TTY_FORCE; else options.request_tty = REQUEST_TTY_YES; break; case 'v': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else { if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; break; } /* FALLTHROUGH */ case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); if (opt == 'V') exit(0); break; case 'w': if (options.tun_open == -1) options.tun_open = SSH_TUNMODE_DEFAULT; options.tun_local = a2tun(optarg, &options.tun_remote); if (options.tun_local == SSH_TUNID_ERR) { fprintf(stderr, "Bad tun device '%s'\n", optarg); exit(255); } break; case 'W': if (stdio_forward_host != NULL) fatal("stdio forward already specified"); if (muxclient_command != 0) fatal("Cannot specify stdio forward with -O"); if (parse_forward(&fwd, optarg, 1, 0)) { stdio_forward_host = fwd.listen_host; stdio_forward_port = fwd.listen_port; xfree(fwd.connect_host); } else { fprintf(stderr, "Bad stdio forwarding specification '%s'\n", optarg); exit(255); } options.request_tty = REQUEST_TTY_NO; no_shell_flag = 1; options.clear_forwardings = 1; options.exit_on_forward_failure = 1; break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'e': if (optarg[0] == '^' && optarg[2] == 0 && (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128) options.escape_char = (u_char) optarg[1] & 31; else if (strlen(optarg) == 1) options.escape_char = (u_char) optarg[0]; else if (strcmp(optarg, "none") == 0) options.escape_char = SSH_ESCAPECHAR_NONE; else { fprintf(stderr, "Bad escape character '%s'.\n", optarg); exit(255); } break; case 'c': if (ciphers_valid(optarg)) { /* SSH2 only */ options.ciphers = xstrdup(optarg); options.cipher = SSH_CIPHER_INVALID; } else { /* SSH1 only */ options.cipher = cipher_number(optarg); if (options.cipher == -1) { fprintf(stderr, "Unknown cipher type '%s'\n", optarg); exit(255); } if (options.cipher == SSH_CIPHER_3DES) options.ciphers = "3des-cbc"; else if (options.cipher == SSH_CIPHER_BLOWFISH) options.ciphers = "blowfish-cbc"; else options.ciphers = (char *)-1; } break; case 'm': if (mac_valid(optarg)) options.macs = xstrdup(optarg); else { fprintf(stderr, "Unknown mac type '%s'\n", optarg); exit(255); } break; case 'M': if (options.control_master == SSHCTL_MASTER_YES) options.control_master = SSHCTL_MASTER_ASK; else options.control_master = SSHCTL_MASTER_YES; break; case 'p': options.port = a2port(optarg); if (options.port <= 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(255); } break; case 'l': options.user = optarg; break; case 'L': if (parse_forward(&fwd, optarg, 0, 0)) add_local_forward(&options, &fwd); else { fprintf(stderr, "Bad local forwarding specification '%s'\n", optarg); exit(255); } break; case 'R': if (parse_forward(&fwd, optarg, 0, 1)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, "Bad remote forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'D': if (parse_forward(&fwd, optarg, 1, 0)) { add_local_forward(&options, &fwd); } else { fprintf(stderr, "Bad dynamic forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'C': options.compression = 1; break; case 'N': no_shell_flag = 1; options.request_tty = REQUEST_TTY_NO; break; case 'T': options.request_tty = REQUEST_TTY_NO; break; case 'o': dummy = 1; line = xstrdup(optarg); if (process_config_line(&options, host ? host : "", line, "command-line", 0, &dummy) != 0) exit(255); xfree(line); break; case 's': subsystem_flag = 1; break; case 'S': if (options.control_path != NULL) free(options.control_path); options.control_path = xstrdup(optarg); break; case 'b': options.bind_address = optarg; break; case 'F': config = optarg; break; default: usage(); } } ac -= optind; av += optind; if (ac > 0 && !host) { if (strrchr(*av, '@')) { p = xstrdup(*av); cp = strrchr(p, '@'); if (cp == NULL || cp == p) usage(); options.user = p; *cp = '\0'; host = ++cp; } else host = *av; if (ac > 1) { optind = optreset = 1; goto again; } ac--, av++; } /* Check that we got a host name. */ if (!host) usage(); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* Initialize the command to execute on remote host. */ buffer_init(&command); if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) tty_flag = 1; /* * Save the command to execute on the remote host in a buffer. There * is no limit on the length of the command, except by the maximum * packet size. Also sets the tty flag if there is no command. */ if (!ac) { /* No command specified - execute shell on a tty. */ tty_flag = options.request_tty != REQUEST_TTY_NO; if (subsystem_flag) { fprintf(stderr, "You must specify a subsystem to invoke.\n"); usage(); } } else { /* A command has been specified. Store it into the buffer. */ for (i = 0; i < ac; i++) { if (i) buffer_append(&command, " ", 1); buffer_append(&command, av[i], strlen(av[i])); } } /* Cannot fork to background if no command. */ if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) fatal("Cannot fork into background without a command " "to execute."); /* Allocate a tty by default if no command specified. */ if (buffer_len(&command) == 0) tty_flag = options.request_tty != REQUEST_TTY_NO; /* Force no tty */ if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0) tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if ((!isatty(fileno(stdin)) || stdin_null_flag) && options.request_tty != REQUEST_TTY_FORCE) { if (tty_flag) logit("Pseudo-terminal will not be allocated because " "stdin is not a terminal."); tty_flag = 0; } /* * Initialize "log" output. Since we are the client all output * actually goes to stderr. */ log_init(argv0, options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, SYSLOG_FACILITY_USER, !use_syslog); /* * Read per-user configuration file. Ignore the system wide config * file if the user specifies a config file on the command line. */ if (config != NULL) { if (!read_config_file(config, host, &options, 0)) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); if (r > 0 && (size_t)r < sizeof(buf)) (void)read_config_file(buf, host, &options, 1); /* Read systemwide configuration file after user config. */ (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options, 0); } /* Fill configuration defaults. */ fill_default_options(&options); channel_set_af(options.address_family); /* reinit */ log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog); seed_rng(); if (options.user == NULL) options.user = xstrdup(pw->pw_name); /* Get default port if port has not been set. */ if (options.port == 0) { sp = getservbyname(SSH_SERVICE_NAME, "tcp"); options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; } /* preserve host name given on command line for %n expansion */ host_arg = host; if (options.hostname != NULL) { host = percent_expand(options.hostname, "h", host, (char *)NULL); } if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); strlcpy(shorthost, thishost, sizeof(shorthost)); shorthost[strcspn(thishost, ".")] = '\0'; snprintf(portstr, sizeof(portstr), "%d", options.port); if (options.local_command != NULL) { debug3("expanding LocalCommand: %s", options.local_command); cp = options.local_command; options.local_command = percent_expand(cp, "d", pw->pw_dir, "h", host, "l", thishost, "n", host_arg, "r", options.user, "p", portstr, "u", pw->pw_name, "L", shorthost, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); xfree(cp); } /* force lowercase for hostkey matching */ if (options.host_key_alias != NULL) { for (p = options.host_key_alias; *p; p++) if (isupper(*p)) *p = (char)tolower(*p); } if (options.proxy_command != NULL && strcmp(options.proxy_command, "none") == 0) { xfree(options.proxy_command); options.proxy_command = NULL; } if (options.control_path != NULL && strcmp(options.control_path, "none") == 0) { xfree(options.control_path); options.control_path = NULL; } if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, original_real_uid); xfree(options.control_path); options.control_path = percent_expand(cp, "h", host, "l", thishost, "n", host_arg, "r", options.user, "p", portstr, "u", pw->pw_name, "L", shorthost, (char *)NULL); xfree(cp); } if (muxclient_command != 0 && options.control_path == NULL) fatal("No ControlPath specified for \"-O\" command"); if (options.control_path != NULL) muxclient(options.control_path); timeout_ms = options.connection_timeout * 1000; /* Open a connection to the remote host. */ if (ssh_connect(host, &hostaddr, options.port, options.address_family, options.connection_attempts, &timeout_ms, options.tcp_keep_alive, #ifdef HAVE_CYGWIN options.use_privileged_port, #else original_effective_uid == 0 && options.use_privileged_port, #endif options.proxy_command) != 0) exit(255); if (timeout_ms > 0) debug3("timeout: %d ms remain after connect", timeout_ms); /* * If we successfully made the connection, load the host private key * in case we will need it later for combined rsa-rhosts * authentication. This must be done before releasing extra * privileges, because the file is only readable by root. * If we cannot access the private keys, load the public keys * instead and try to execute the ssh-keysign helper instead. */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; sensitive_data.external_keysign = 0; if (options.rhosts_rsa_authentication || options.hostbased_authentication) { sensitive_data.nkeys = 7; sensitive_data.keys = xcalloc(sensitive_data.nkeys, sizeof(Key)); for (i = 0; i < sensitive_data.nkeys; i++) sensitive_data.keys[i] = NULL; PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL, NULL); sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL); #ifdef OPENSSL_HAS_ECC sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA, _PATH_HOST_ECDSA_KEY_FILE, "", NULL); #endif sensitive_data.keys[3] = key_load_private_cert(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL); sensitive_data.keys[4] = key_load_private_type(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); #ifdef OPENSSL_HAS_ECC sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA, _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL); #endif sensitive_data.keys[6] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); PRIV_END; if (options.hostbased_authentication == 1 && sensitive_data.keys[0] == NULL && sensitive_data.keys[4] == NULL && sensitive_data.keys[5] == NULL && sensitive_data.keys[6] == NULL) { sensitive_data.keys[1] = key_load_cert( _PATH_HOST_DSA_KEY_FILE); #ifdef OPENSSL_HAS_ECC sensitive_data.keys[2] = key_load_cert( _PATH_HOST_ECDSA_KEY_FILE); #endif sensitive_data.keys[3] = key_load_cert( _PATH_HOST_RSA_KEY_FILE); sensitive_data.keys[4] = key_load_public( _PATH_HOST_DSA_KEY_FILE, NULL); #ifdef OPENSSL_HAS_ECC sensitive_data.keys[5] = key_load_public( _PATH_HOST_ECDSA_KEY_FILE, NULL); #endif sensitive_data.keys[6] = key_load_public( _PATH_HOST_RSA_KEY_FILE, NULL); sensitive_data.external_keysign = 1; } } /* * Get rid of any extra privileges that we may have. We will no * longer need them. Also, extra privileges could make it very hard * to read identity files and other non-world-readable files from the * user's home directory if it happens to be on a NFS volume where * root is mapped to nobody. */ if (original_effective_uid == 0) { PRIV_START; permanently_set_uid(pw); } /* * Now that we are back to our own permissions, create ~/.ssh * directory if it doesn't already exist. */ if (config == NULL) { r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { #ifdef WITH_SELINUX ssh_selinux_setfscreatecon(buf); #endif if (mkdir(buf, 0700) < 0) error("Could not create directory '%.200s'.", buf); #ifdef WITH_SELINUX ssh_selinux_setfscreatecon(NULL); #endif } } /* load options.identity_files */ load_public_identity_files(); /* Expand ~ in known host file names. */ tilde_expand_paths(options.system_hostfiles, options.num_system_hostfiles); tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ signal(SIGCHLD, main_sigchld_handler); /* Log into the remote system. Never returns if the login fails. */ ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, options.port, pw, timeout_ms); if (packet_connection_is_on_socket()) { verbose("Authenticated to %s ([%s]:%d).", host, get_remote_ipaddr(), get_remote_port()); } else { verbose("Authenticated to %s (via proxy).", host); } /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { for (i = 0; i < sensitive_data.nkeys; i++) { if (sensitive_data.keys[i] != NULL) { /* Destroys contents safely */ debug3("clear hostkey %d", i); key_free(sensitive_data.keys[i]); sensitive_data.keys[i] = NULL; } } xfree(sensitive_data.keys); } for (i = 0; i < options.num_identity_files; i++) { if (options.identity_files[i]) { xfree(options.identity_files[i]); options.identity_files[i] = NULL; } if (options.identity_keys[i]) { key_free(options.identity_keys[i]); options.identity_keys[i] = NULL; } } exit_status = compat20 ? ssh_session2() : ssh_session(); packet_close(); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); /* Kill ProxyCommand if it is running. */ ssh_kill_proxy_command(); return exit_status; }
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); }