int main(int argc, char **argv) { struct group *gr; struct stat st; int retries, backoff; int ask, ch, cnt, quietlog, rootlogin, rval; uid_t uid, euid; gid_t egid; char *term; char *p, *ttyn; char tname[sizeof(_PATH_TTY) + 10]; char *arg0; const char *tp; const char *shell = NULL; login_cap_t *lc = NULL; login_cap_t *lc_user = NULL; pid_t pid; #ifdef USE_BSM_AUDIT char auditsuccess = 1; #endif signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); if (setjmp(timeout_buf)) { if (failures) badlogin(username); fprintf(stderr, "Login timed out after %d seconds\n", timeout); bail(NO_SLEEP_EXIT, 0); } signal(SIGALRM, timedout); alarm(timeout); setpriority(PRIO_PROCESS, 0, 0); openlog("login", LOG_ODELAY, LOG_AUTH); uid = getuid(); euid = geteuid(); egid = getegid(); while ((ch = getopt(argc, argv, "fh:p")) != -1) switch (ch) { case 'f': fflag = 1; break; case 'h': if (uid != 0) errx(1, "-h option: %s", strerror(EPERM)); if (strlen(optarg) >= MAXHOSTNAMELEN) errx(1, "-h option: %s: exceeds maximum " "hostname size", optarg); hflag = 1; hostname = optarg; break; case 'p': pflag = 1; break; case '?': default: if (uid == 0) syslog(LOG_ERR, "invalid flag %c", ch); usage(); } argc -= optind; argv += optind; if (argc > 0) { username = strdup(*argv); if (username == NULL) err(1, "strdup()"); ask = 0; } else { ask = 1; } setproctitle("-%s", getprogname()); for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); /* * Get current TTY */ ttyn = ttyname(STDIN_FILENO); if (ttyn == NULL || *ttyn == '\0') { snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); ttyn = tname; } if (strncmp(ttyn, _PATH_DEV, sizeof(_PATH_DEV) -1) == 0) tty = ttyn + sizeof(_PATH_DEV) -1; else tty = ttyn; /* * Get "login-retries" & "login-backoff" from default class */ lc = login_getclass(NULL); prompt = login_getcapstr(lc, "login_prompt", default_prompt, default_prompt); passwd_prompt = login_getcapstr(lc, "passwd_prompt", default_passwd_prompt, default_passwd_prompt); retries = login_getcapnum(lc, "login-retries", DEFAULT_RETRIES, DEFAULT_RETRIES); backoff = login_getcapnum(lc, "login-backoff", DEFAULT_BACKOFF, DEFAULT_BACKOFF); login_close(lc); lc = NULL; /* * Try to authenticate the user until we succeed or time out. */ for (cnt = 0;; ask = 1) { if (ask) { fflag = 0; if (olduser != NULL) free(olduser); olduser = username; username = getloginname(); } rootlogin = 0; /* * Note if trying multiple user names; log failures for * previous user name, but don't bother logging one failure * for nonexistent name (mistyped username). */ if (failures && strcmp(olduser, username) != 0) { if (failures > (pwd ? 0 : 1)) badlogin(olduser); } /* * Load the PAM policy and set some variables */ pam_err = pam_start("login", username, &pamc, &pamh); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_start()"); #ifdef USE_BSM_AUDIT au_login_fail("PAM Error", 1); #endif bail(NO_SLEEP_EXIT, 1); } pam_err = pam_set_item(pamh, PAM_TTY, tty); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_set_item(PAM_TTY)"); #ifdef USE_BSM_AUDIT au_login_fail("PAM Error", 1); #endif bail(NO_SLEEP_EXIT, 1); } pam_err = pam_set_item(pamh, PAM_RHOST, hostname); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_set_item(PAM_RHOST)"); #ifdef USE_BSM_AUDIT au_login_fail("PAM Error", 1); #endif bail(NO_SLEEP_EXIT, 1); } pwd = getpwnam(username); if (pwd != NULL && pwd->pw_uid == 0) rootlogin = 1; /* * If the -f option was specified and the caller is * root or the caller isn't changing their uid, don't * authenticate. */ if (pwd != NULL && fflag && (uid == (uid_t)0 || uid == (uid_t)pwd->pw_uid)) { /* already authenticated */ rval = 0; #ifdef USE_BSM_AUDIT auditsuccess = 0; /* opened a terminal window only */ #endif } else { fflag = 0; setpriority(PRIO_PROCESS, 0, -4); rval = auth_pam(); setpriority(PRIO_PROCESS, 0, 0); } if (pwd && rval == 0) break; pam_cleanup(); /* * We are not exiting here, but this corresponds to a failed * login event, so set exitstatus to 1. */ #ifdef USE_BSM_AUDIT au_login_fail("Login incorrect", 1); #endif printf("Login incorrect\n"); failures++; pwd = NULL; /* * Allow up to 'retry' (10) attempts, but start * backing off after 'backoff' (3) attempts. */ if (++cnt > backoff) { if (cnt >= retries) { badlogin(username); bail(SLEEP_EXIT, 1); } sleep((u_int)((cnt - backoff) * 5)); } } /* committed to login -- turn off timeout */ alarm((u_int)0); signal(SIGHUP, SIG_DFL); endpwent(); #ifdef USE_BSM_AUDIT /* Audit successful login. */ if (auditsuccess) au_login_success(); #endif /* * Establish the login class. */ lc = login_getpwclass(pwd); lc_user = login_getuserclass(pwd); if (!(quietlog = login_getcapbool(lc_user, "hushlogin", 0))) quietlog = login_getcapbool(lc, "hushlogin", 0); /* * Switching needed for NFS with root access disabled. * * XXX: This change fails to modify the additional groups for the * process, and as such, may restrict rights normally granted * through those groups. */ setegid(pwd->pw_gid); seteuid(rootlogin ? 0 : pwd->pw_uid); if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) { if (login_getcapbool(lc, "requirehome", 0)) refused("Home directory not available", "HOMEDIR", 1); if (chdir("/") < 0) refused("Cannot find root directory", "ROOTDIR", 1); if (!quietlog || *pwd->pw_dir) printf("No home directory.\nLogging in with home = \"/\".\n"); pwd->pw_dir = strdup("/"); if (pwd->pw_dir == NULL) { syslog(LOG_NOTICE, "strdup(): %m"); bail(SLEEP_EXIT, 1); } } seteuid(euid); setegid(egid); if (!quietlog) { quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; if (!quietlog) pam_silent = 0; } shell = login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell); if (*pwd->pw_shell == '\0') pwd->pw_shell = strdup(_PATH_BSHELL); if (pwd->pw_shell == NULL) { syslog(LOG_NOTICE, "strdup(): %m"); bail(SLEEP_EXIT, 1); } if (*shell == '\0') /* Not overridden */ shell = pwd->pw_shell; if ((shell = strdup(shell)) == NULL) { syslog(LOG_NOTICE, "strdup(): %m"); bail(SLEEP_EXIT, 1); } /* * Set device protections, depending on what terminal the * user is logged in. This feature is used on Suns to give * console users better privacy. */ login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); /* * Clear flags of the tty. None should be set, and when the * user sets them otherwise, this can cause the chown to fail. * Since it isn't clear that flags are useful on character * devices, we just clear them. * * We don't log in the case of EOPNOTSUPP because dev might be * on NFS, which doesn't support chflags. * * We don't log in the EROFS because that means that /dev is on * a read only file system and we assume that the permissions there * are sane. */ if (ttyn != tname && chflags(ttyn, 0)) if (errno != EOPNOTSUPP && errno != EROFS) syslog(LOG_ERR, "chflags(%s): %m", ttyn); if (ttyn != tname && chown(ttyn, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid)) if (errno != EROFS) syslog(LOG_ERR, "chown(%s): %m", ttyn); /* * Exclude cons/vt/ptys only, assume dialup otherwise * TODO: Make dialup tty determination a library call * for consistency (finger etc.) */ if (hflag && isdialuptty(tty)) syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); #ifdef LOGALL /* * Syslog each successful login, so we don't have to watch * hundreds of wtmp or lastlogin files. */ if (hflag) syslog(LOG_INFO, "login from %s on %s as %s", hostname, tty, pwd->pw_name); else syslog(LOG_INFO, "login on %s as %s", tty, pwd->pw_name); #endif /* * If fflag is on, assume caller/authenticator has logged root * login. */ if (rootlogin && fflag == 0) { if (hflag) syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", username, tty, hostname); else syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); } /* * Destroy environment unless user has requested its * preservation - but preserve TERM in all cases */ term = getenv("TERM"); if (!pflag) environ = envinit; if (term != NULL) { if (setenv("TERM", term, 0) == -1) err(1, "setenv: cannot set TERM=%s", term); } /* * PAM modules might add supplementary groups during pam_setcred(). */ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) { syslog(LOG_ERR, "setusercontext() failed - exiting"); bail(NO_SLEEP_EXIT, 1); } pam_err = pam_setcred(pamh, pam_silent|PAM_ESTABLISH_CRED); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_setcred()"); bail(NO_SLEEP_EXIT, 1); } pam_cred_established = 1; pam_err = pam_open_session(pamh, pam_silent); if (pam_err != PAM_SUCCESS) { pam_syslog("pam_open_session()"); bail(NO_SLEEP_EXIT, 1); } pam_session_established = 1; /* * We must fork() before setuid() because we need to call * pam_close_session() as root. */ pid = fork(); if (pid < 0) { err(1, "fork"); } else if (pid != 0) { /* * Parent: wait for child to finish, then clean up * session. */ int status; setproctitle("-%s [pam]", getprogname()); waitpid(pid, &status, 0); bail(NO_SLEEP_EXIT, 0); } /* * NOTICE: We are now in the child process! */ /* * Add any environment variables the PAM modules may have set. */ export_pam_environment(); /* * We're done with PAM now; our parent will deal with the rest. */ pam_end(pamh, 0); pamh = NULL; /* * We don't need to be root anymore, so set the login name and * the UID. */ if (setlogin(username) != 0) { syslog(LOG_ERR, "setlogin(%s): %m - exiting", username); bail(NO_SLEEP_EXIT, 1); } if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL & ~(LOGIN_SETLOGIN|LOGIN_SETGROUP)) != 0) { syslog(LOG_ERR, "setusercontext() failed - exiting"); exit(1); } if (setenv("SHELL", pwd->pw_shell, 1) == -1) err(1, "setenv: cannot set SHELL=%s", pwd->pw_shell); if (setenv("HOME", pwd->pw_dir, 1) == -1) err(1, "setenv: cannot set HOME=%s", pwd->pw_dir); /* Overwrite "term" from login.conf(5) for any known TERM */ if (term == NULL && (tp = stypeof(tty)) != NULL) { if (setenv("TERM", tp, 1) == -1) err(1, "setenv: cannot set TERM=%s", tp); } else { if (setenv("TERM", TERM_UNKNOWN, 0) == -1) err(1, "setenv: cannot set TERM=%s", TERM_UNKNOWN); } if (setenv("LOGNAME", username, 1) == -1) err(1, "setenv: cannot set LOGNAME=%s", username); if (setenv("USER", username, 1) == -1) err(1, "setenv: cannot set USER=%s", username); if (setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0) == -1) { err(1, "setenv: cannot set PATH=%s", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH); } if (!quietlog) { const char *cw; cw = login_getcapstr(lc, "copyright", NULL, NULL); if (cw == NULL || motd(cw) == -1) printf("%s", copyright); printf("\n"); cw = login_getcapstr(lc, "welcome", NULL, NULL); if (cw != NULL && access(cw, F_OK) == 0) motd(cw); else motd(_PATH_MOTDFILE); if (login_getcapbool(lc_user, "nocheckmail", 0) == 0 && login_getcapbool(lc, "nocheckmail", 0) == 0) { char *cx; /* $MAIL may have been set by class. */ cx = getenv("MAIL"); if (cx == NULL) { asprintf(&cx, "%s/%s", _PATH_MAILDIR, pwd->pw_name); } if (cx && stat(cx, &st) == 0 && st.st_size != 0) printf("You have %smail.\n", (st.st_mtime > st.st_atime) ? "new " : ""); if (getenv("MAIL") == NULL) free(cx); } } login_close(lc_user); login_close(lc); signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGTSTP, SIG_IGN); /* * Login shells have a leading '-' in front of argv[0] */ p = strrchr(pwd->pw_shell, '/'); if (asprintf(&arg0, "-%s", p ? p + 1 : pwd->pw_shell) >= MAXPATHLEN) { syslog(LOG_ERR, "user: %s: shell exceeds maximum pathname size", username); errx(1, "shell exceeds maximum pathname size"); } else if (arg0 == NULL) { err(1, "asprintf()"); } execlp(shell, arg0, NULL); err(1, "%s", shell); /* * That's it, folks! */ }
int main(int argc, char **argv) { int c; int cnt; char *childArgv[10]; char *buff; int childArgc = 0; int retcode; char *pwdbuf = NULL; struct passwd *pwd = NULL, _pwd; struct login_context cxt = { .tty_mode = TTY_MODE, /* tty chmod() */ .pid = getpid(), /* PID */ .conv = { misc_conv, NULL } /* PAM conversation function */ }; timeout = (unsigned int)getlogindefs_num("LOGIN_TIMEOUT", LOGIN_TIMEOUT); signal(SIGALRM, timedout); siginterrupt(SIGALRM, 1); /* we have to interrupt syscalls like ioclt() */ alarm(timeout); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); setpriority(PRIO_PROCESS, 0, 0); initproctitle(argc, argv); /* * -p is used by getty to tell login not to destroy the environment * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote * host to login so that it may be placed in utmp and wtmp */ while ((c = getopt(argc, argv, "fHh:pV")) != -1) switch (c) { case 'f': cxt.noauth = 1; break; case 'H': cxt.nohost = 1; break; case 'h': if (getuid()) { fprintf(stderr, _("login: -h for super-user only.\n")); exit(EXIT_FAILURE); } init_remote_info(&cxt, optarg); break; case 'p': cxt.keep_env = 1; break; case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case '?': default: fprintf(stderr, _("usage: login [ -p ] [ -h host ] [ -H ] [ -f username | username ]\n")); exit(EXIT_FAILURE); } argc -= optind; argv += optind; if (*argv) { char *p = *argv; cxt.username = xstrdup(p); /* wipe name - some people mistype their password here */ /* (of course we are too late, but perhaps this helps a little ..) */ while (*p) *p++ = ' '; } for (cnt = get_fd_tabsize() - 1; cnt > 2; cnt--) close(cnt); setpgrp(); /* set pgid to pid this means that setsid() will fail */ openlog("login", LOG_ODELAY, LOG_AUTHPRIV); init_tty(&cxt); init_loginpam(&cxt); /* login -f, then the user has already been authenticated */ cxt.noauth = cxt.noauth && getuid() == 0 ? 1 : 0; if (!cxt.noauth) loginpam_auth(&cxt); /* * Authentication may be skipped (for example, during krlogin, rlogin, * etc...), but it doesn't mean that we can skip other account checks. * The account could be disabled or password expired (although * kerberos ticket is valid). -- [email protected] (22-Feb-2006) */ loginpam_acct(&cxt); if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) { warnx(_("\nSession setup problem, abort.")); syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."), cxt.username, __FUNCTION__, __LINE__); pam_end(cxt.pamh, PAM_SYSTEM_ERR); sleepexit(EXIT_FAILURE); } pwd = cxt.pwd; cxt.username = pwd->pw_name; /* * Initialize the supplementary group list. This should be done before * pam_setcred because the PAM modules might add groups during * pam_setcred. * * For root we don't call initgroups, instead we call setgroups with * group 0. This avoids the need to step through the whole group file, * which can cause problems if NIS, NIS+, LDAP or something similar * is used and the machine has network problems. */ retcode = pwd->pw_uid ? initgroups(cxt.username, pwd->pw_gid) : /* user */ setgroups(0, NULL); /* root */ if (retcode < 0) { syslog(LOG_ERR, _("groups initialization failed: %m")); warnx(_("\nSession setup problem, abort.")); pam_end(cxt.pamh, PAM_SYSTEM_ERR); sleepexit(EXIT_FAILURE); } /* * Open PAM session (after successful authentication and account check) */ loginpam_session(&cxt); /* committed to login -- turn off timeout */ alarm((unsigned int)0); endpwent(); cxt.quiet = get_hushlogin_status(pwd); log_utmp(&cxt); log_audit(&cxt, 1); log_lastlog(&cxt); chown_tty(&cxt); if (setgid(pwd->pw_gid) < 0 && pwd->pw_gid) { syslog(LOG_ALERT, _("setgid() failed")); exit(EXIT_FAILURE); } if (pwd->pw_shell == NULL || *pwd->pw_shell == '\0') pwd->pw_shell = _PATH_BSHELL; init_environ(&cxt); /* init $HOME, $TERM ... */ setproctitle("login", cxt.username); log_syslog(&cxt); if (!cxt.quiet) { motd(); #ifdef LOGIN_STAT_MAIL /* * This turns out to be a bad idea: when the mail spool * is NFS mounted, and the NFS connection hangs, the * login hangs, even root cannot login. * Checking for mail should be done from the shell. */ { struct stat st; char *mail; mail = getenv("MAIL"); if (mail && stat(mail, &st) == 0 && st.st_size != 0) { if (st.st_mtime > st.st_atime) printf(_("You have new mail.\n")); else printf(_("You have mail.\n")); } } #endif } /* * Detach the controlling terminal, fork() and create, new session * and reinilizalize syslog stuff. */ fork_session(&cxt); /* discard permissions last so can't get killed and drop core */ if (setuid(pwd->pw_uid) < 0 && pwd->pw_uid) { syslog(LOG_ALERT, _("setuid() failed")); exit(EXIT_FAILURE); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { warn(_("%s: change directory failed"), pwd->pw_dir); if (!getlogindefs_bool("DEFAULT_HOME", 1)) exit(0); if (chdir("/")) exit(EXIT_FAILURE); pwd->pw_dir = "/"; printf(_("Logging in with home = \"/\".\n")); } /* if the shell field has a space: treat it like a shell script */ if (strchr(pwd->pw_shell, ' ')) { buff = xmalloc(strlen(pwd->pw_shell) + 6); strcpy(buff, "exec "); strcat(buff, pwd->pw_shell); childArgv[childArgc++] = "/bin/sh"; childArgv[childArgc++] = "-sh"; childArgv[childArgc++] = "-c"; childArgv[childArgc++] = buff; } else { char tbuf[PATH_MAX + 2], *p; tbuf[0] = '-'; xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell), sizeof(tbuf) - 1); childArgv[childArgc++] = pwd->pw_shell; childArgv[childArgc++] = xstrdup(tbuf); } childArgv[childArgc++] = NULL; execvp(childArgv[0], childArgv + 1); if (!strcmp(childArgv[0], "/bin/sh")) warn(_("couldn't exec shell script")); else warn(_("no shell")); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int ch, np, ret, Xflag = 0; pcap_handler phandler = dump_packet; const char *errstr = NULL; char *pidf = NULL; ret = 0; closefrom(STDERR_FILENO + 1); while ((ch = getopt(argc, argv, "Dxd:f:i:p:s:")) != -1) { switch (ch) { case 'D': Debug = 1; break; case 'd': delay = strtonum(optarg, 5, 60*60, &errstr); if (errstr) usage(); break; case 'f': filename = optarg; break; case 'i': interface = optarg; break; case 'p': pidf = optarg; break; case 's': snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN, &errstr); if (snaplen <= 0) snaplen = DEF_SNAPLEN; if (errstr) snaplen = PFLOGD_MAXSNAPLEN; break; case 'x': Xflag++; break; default: usage(); } } log_debug = Debug; argc -= optind; argv += optind; /* does interface exist */ if (!if_exists(interface)) { warn("Failed to initialize: %s", interface); logmsg(LOG_ERR, "Failed to initialize: %s", interface); logmsg(LOG_ERR, "Exiting, init failure"); exit(1); } if (!Debug) { openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON); if (daemon(0, 0)) { logmsg(LOG_WARNING, "Failed to become daemon: %s", strerror(errno)); } pidfile(pidf); } tzset(); (void)umask(S_IRWXG | S_IRWXO); /* filter will be used by the privileged process */ if (argc) { filter = copy_argv(argv); if (filter == NULL) logmsg(LOG_NOTICE, "Failed to form filter expression"); } /* initialize pcap before dropping privileges */ if (init_pcap()) { logmsg(LOG_ERR, "Exiting, init failure"); exit(1); } /* Privilege separation begins here */ if (priv_init()) { logmsg(LOG_ERR, "unable to privsep"); exit(1); } setproctitle("[initializing]"); /* Process is now unprivileged and inside a chroot */ signal(SIGTERM, sig_close); signal(SIGINT, sig_close); signal(SIGQUIT, sig_close); signal(SIGALRM, sig_alrm); signal(SIGUSR1, sig_usr1); signal(SIGHUP, sig_hup); alarm(delay); buffer = malloc(PFLOGD_BUFSIZE); if (buffer == NULL) { logmsg(LOG_WARNING, "Failed to allocate output buffer"); phandler = dump_packet_nobuf; } else { bufleft = buflen = PFLOGD_BUFSIZE; bufpos = buffer; bufpkt = 0; } if (reset_dump(Xflag) < 0) { if (Xflag) return (1); logmsg(LOG_ERR, "Logging suspended: open error"); set_suspended(1); } else if (Xflag) return (0); while (1) { np = pcap_dispatch(hpcap, PCAP_NUM_PKTS, phandler, (u_char *)dpcap); if (np < 0) { if (!if_exists(interface) == -1) { logmsg(LOG_NOTICE, "interface %s went away", interface); ret = -1; break; } logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap)); } if (gotsig_close) break; if (gotsig_hup) { if (reset_dump(0)) { logmsg(LOG_ERR, "Logging suspended: open error"); set_suspended(1); } gotsig_hup = 0; } if (gotsig_alrm) { if (dpcap) flush_buffer(dpcap); else gotsig_hup = 1; gotsig_alrm = 0; alarm(delay); } if (gotsig_usr1) { log_pcap_stats(); gotsig_usr1 = 0; } } logmsg(LOG_NOTICE, "Exiting"); if (dpcap) { flush_buffer(dpcap); fclose(dpcap); } purge_buffer(); log_pcap_stats(); pcap_close(hpcap); if (!Debug) closelog(); return (ret); }
/* * Generic function to handle CRIU_REQ_TYPE__FEATURE_CHECK. * * The function will have resp.success = true for most cases * and the actual result will be in resp.features. * * For each feature which has been requested in msg->features * the corresponding parameter will be set in resp.features. */ static int handle_feature_check(int sk, CriuReq * msg) { CriuResp resp = CRIU_RESP__INIT; CriuFeatures feat = CRIU_FEATURES__INIT; int pid, status; int ret; /* enable setting of an optional message */ feat.has_mem_track = 1; feat.mem_track = false; feat.has_lazy_pages = 1; feat.lazy_pages = false; pid = fork(); if (pid < 0) { pr_perror("Can't fork"); goto out; } if (pid == 0) { /* kerndat_init() is called from setup_opts_from_req() */ if (setup_opts_from_req(sk, msg->opts)) exit(1); setproctitle("feature-check --rpc"); if ((msg->features->has_mem_track == 1) && (msg->features->mem_track == true)) feat.mem_track = kdat.has_dirty_track; if ((msg->features->has_lazy_pages == 1) && (msg->features->lazy_pages == true)) feat.lazy_pages = kdat.has_uffd && uffd_noncooperative(); resp.features = &feat; resp.type = msg->type; /* The feature check is working, actual results are in resp.features */ resp.success = true; /* * If this point is reached the information about the features * is transmitted from the forked CRIU process (here). * If an error occurred earlier, the feature check response will be * be send from the parent process. */ ret = send_criu_msg(sk, &resp); exit(!!ret); } if (waitpid(pid, &status, 0) != pid) { pr_perror("Unable to wait %d", pid); goto out; } if (status != 0) goto out; /* * The child process was not able to send an answer. Tell * the RPC client that something did not work as expected. */ out: resp.type = msg->type; resp.success = false; return send_criu_msg(sk, &resp); }
int main(int argc, char *argv[]) { int c, error, gdb_port, err, bvmcons; int max_vcpus; struct vmctx *ctx; uint64_t rip; size_t memsize; bvmcons = 0; progname = basename(argv[0]); gdb_port = 0; guest_ncpus = 1; memsize = 256 * MB; while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) { switch (c) { case 'a': x2apic_mode = 0; break; case 'A': acpi = 1; break; case 'b': bvmcons = 1; break; case 'p': pincpu = atoi(optarg); break; case 'c': guest_ncpus = atoi(optarg); break; case 'g': gdb_port = atoi(optarg); break; case 'l': if (lpc_device_parse(optarg) != 0) { errx(EX_USAGE, "invalid lpc device " "configuration '%s'", optarg); } break; case 's': if (pci_parse_slot(optarg) != 0) exit(1); else break; case 'm': error = vm_parse_memsize(optarg, &memsize); if (error) errx(EX_USAGE, "invalid memsize '%s'", optarg); break; case 'H': guest_vmexit_on_hlt = 1; break; case 'I': /* * The "-I" option was used to add an ioapic to the * virtual machine. * * An ioapic is now provided unconditionally for each * virtual machine and this option is now deprecated. */ break; case 'P': guest_vmexit_on_pause = 1; break; case 'e': strictio = 1; break; case 'U': guest_uuid_str = optarg; break; case 'w': strictmsr = 0; break; case 'W': virtio_msix = 0; break; case 'x': x2apic_mode = 1; break; case 'h': usage(0); default: usage(1); } } argc -= optind; argv += optind; if (argc != 1) usage(1); vmname = argv[0]; ctx = vm_open(vmname); if (ctx == NULL) { perror("vm_open"); exit(1); } max_vcpus = num_vcpus_allowed(ctx); if (guest_ncpus > max_vcpus) { fprintf(stderr, "%d vCPUs requested but only %d available\n", guest_ncpus, max_vcpus); exit(1); } fbsdrun_set_capabilities(ctx, BSP); err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL); if (err) { fprintf(stderr, "Unable to setup memory (%d)\n", err); exit(1); } init_mem(); init_inout(); ioapic_init(ctx); rtc_init(ctx); /* * Exit if a device emulation finds an error in it's initilization */ if (init_pci(ctx) != 0) exit(1); if (gdb_port != 0) init_dbgport(gdb_port); if (bvmcons) init_bvmcons(); error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); assert(error == 0); /* * build the guest tables, MP etc. */ mptable_build(ctx, guest_ncpus); error = smbios_build(ctx); assert(error == 0); if (acpi) { error = acpi_build(ctx, guest_ncpus); assert(error == 0); } /* * Change the proc title to include the VM name. */ setproctitle("%s", vmname); /* * Add CPU 0 */ fbsdrun_addcpu(ctx, BSP, BSP, rip); /* * Head off to the main event dispatch loop */ mevent_dispatch(); exit(1); }
int main(int argc, char *argv[]) { extern char *optarg; /* argument to option if any */ int i; /* counter in a for loop */ char *p; /* used to obtain the key */ DES_cblock msgbuf; /* I/O buffer */ int kflag; /* command-line encryption key */ setproctitle("-"); /* Hide command-line arguments */ /* initialize the initialization vector */ MEMZERO(ivec, 8); /* process the argument list */ kflag = 0; while ((i = getopt(argc, argv, "abdF:f:k:m:o:pv:")) != -1) switch(i) { case 'a': /* key is ASCII */ keybase = KEY_ASCII; break; case 'b': /* use ECB mode */ alg = ALG_ECB; break; case 'd': /* decrypt */ mode = MODE_DECRYPT; break; case 'F': /* use alternative CFB mode */ alg = ALG_CFBA; if ((fbbits = setbits(optarg, 7)) > 56 || fbbits == 0) errx(1, "-F: number must be 1-56 inclusive"); else if (fbbits == -1) errx(1, "-F: number must be a multiple of 7"); break; case 'f': /* use CFB mode */ alg = ALG_CFB; if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) errx(1, "-f: number must be 1-64 inclusive"); else if (fbbits == -1) errx(1, "-f: number must be a multiple of 8"); break; case 'k': /* encryption key */ kflag = 1; cvtkey(msgbuf, optarg); break; case 'm': /* number of bits for MACing */ mode = MODE_AUTHENTICATE; if ((macbits = setbits(optarg, 1)) > 64) errx(1, "-m: number must be 0-64 inclusive"); break; case 'o': /* use OFB mode */ alg = ALG_OFB; if ((fbbits = setbits(optarg, 8)) > 64 || fbbits == 0) errx(1, "-o: number must be 1-64 inclusive"); else if (fbbits == -1) errx(1, "-o: number must be a multiple of 8"); break; case 'p': /* preserve parity bits */ pflag = 1; break; case 'v': /* set initialization vector */ cvtkey(ivec, optarg); break; default: /* error */ usage(); } if (!kflag) { /* * if the key's not ASCII, assume it is */ keybase = KEY_ASCII; /* * get the key */ p = getpass("Enter key: "); /* * copy it, nul-padded, into the key area */ cvtkey(msgbuf, p); } makekey(&msgbuf); inverse = (alg == ALG_CBC || alg == ALG_ECB) && mode == MODE_DECRYPT; switch(alg) { case ALG_CBC: switch(mode) { case MODE_AUTHENTICATE: /* authenticate using CBC mode */ cbcauth(); break; case MODE_DECRYPT: /* decrypt using CBC mode */ cbcdec(); break; case MODE_ENCRYPT: /* encrypt using CBC mode */ cbcenc(); break; } break; case ALG_CFB: switch(mode) { case MODE_AUTHENTICATE: /* authenticate using CFB mode */ cfbauth(); break; case MODE_DECRYPT: /* decrypt using CFB mode */ cfbdec(); break; case MODE_ENCRYPT: /* encrypt using CFB mode */ cfbenc(); break; } break; case ALG_CFBA: switch(mode) { case MODE_AUTHENTICATE: /* authenticate using CFBA mode */ errx(1, "can't authenticate with CFBA mode"); break; case MODE_DECRYPT: /* decrypt using CFBA mode */ cfbadec(); break; case MODE_ENCRYPT: /* encrypt using CFBA mode */ cfbaenc(); break; } break; case ALG_ECB: switch(mode) { case MODE_AUTHENTICATE: /* authenticate using ECB mode */ errx(1, "can't authenticate with ECB mode"); break; case MODE_DECRYPT: /* decrypt using ECB mode */ ecbdec(); break; case MODE_ENCRYPT: /* encrypt using ECB mode */ ecbenc(); break; } break; case ALG_OFB: switch(mode) { case MODE_AUTHENTICATE: /* authenticate using OFB mode */ errx(1, "can't authenticate with OFB mode"); break; case MODE_DECRYPT: /* decrypt using OFB mode */ ofbdec(); break; case MODE_ENCRYPT: /* encrypt using OFB mode */ ofbenc(); break; } break; } return (0); }
int utmpfix(int argc, char **argv) { int i, fast = 0, nownum = SHM->UTMPnumber; int which, nactive = 0, dofork = 1, daemonsleep = 0; time_t now; const char *clean; char buf[1024]; IDLE_t idle[USHM_SIZE]; char changeflag = 0; time_t idletimeout = IDLE_TIMEOUT; int lowerbound = 100, upperbound = 0; char ch; int killtop = 0; struct { pid_t pid; int where; } killlist[USHM_SIZE]; while( (ch = getopt(argc, argv, "nt:l:FD:u:")) != -1 ) switch( ch ){ case 'n': fast = 1; break; case 't': idletimeout = atoi(optarg); break; case 'l': lowerbound = atoi(optarg); break; case 'F': dofork = 0; break; case 'D': daemonsleep = atoi(optarg); break; case 'u': upperbound = atoi(optarg); break; default: printf("usage:\tshmctl\tutmpfix [-n] [-t timeout] [-F] [-D sleep]\n"); return 1; } if( daemonsleep ) switch( fork() ){ case -1: perror("fork()"); return 0; case 0: break; default: return 0; } if( daemonsleep || dofork ){ int times = 1000, status; pid_t pid; while( daemonsleep ? 1 : times-- ) switch( pid = fork() ){ case -1: sleep(1); break; case 0: #ifndef VALGRIND setproctitle("utmpfix"); #endif goto DoUtmpfix; default: #ifndef VALGRIND setproctitle(daemonsleep ? "utmpfixd(wait for %d)" : "utmpfix(wait for %d)", (int)pid); #endif waitpid(pid, &status, 0); if( WIFEXITED(status) && !daemonsleep ) return 0; if( !WIFEXITED(status) ){ /* last utmpfix fails, so SHM->UTMPbusystate is holded */ SHM->UTMPbusystate = 0; } } return 0; // never reach } DoUtmpfix: killtop=0; changeflag=0; for( i = 0 ; i < 5 ; ++i ) if( !SHM->UTMPbusystate ) break; else{ puts("utmpshm is busy...."); sleep(1); } SHM->UTMPbusystate = 1; printf("starting scaning... %s \n", (fast ? "(fast mode)" : "")); nownum = SHM->UTMPnumber; now = time(NULL); for( i = 0, nactive = 0 ; i < USHM_SIZE ; ++i ) if( SHM->uinfo[i].pid ){ idle[nactive].index = i; idle[nactive].idle = now - SHM->uinfo[i].lastact; ++nactive; } if( !fast ) qsort(idle, nactive, sizeof(IDLE_t), sfIDLE); #define addkilllist(a) \ do { \ pid_t pid=SHM->uinfo[(a)].pid; \ if(pid > 0) { \ killlist[killtop].where = (a); \ killlist[killtop++].pid = pid; \ } \ } while( 0 ) for( i = 0 ; i < nactive ; ++i ){ which = idle[i].index; clean = NULL; if( !isalpha(SHM->uinfo[which].userid[0]) ){ clean = "userid error"; addkilllist(which); } else if( memchr(SHM->uinfo[which].userid, '\0', IDLEN + 1) == NULL ){ clean = "userid without z"; addkilllist(which); } else if( SHM->uinfo[which].friendtotal > MAX_FRIEND || SHM->uinfo[which].friendtotal<0 ){ clean = "too many/less friend"; addkilllist(which); } else if( searchuser(SHM->uinfo[which].userid, NULL) == 0 ){ clean = "user not exist"; addkilllist(which); } else if( kill(SHM->uinfo[which].pid, 0) < 0 ){ /* 此條件應放最後; 其他欄位沒問題但 process 不存在才 purge_utmp */ clean = "process error"; purge_utmp(&SHM->uinfo[which]); } #ifdef DOTIMEOUT else if( (strcasecmp(SHM->uinfo[which].userid, STR_GUEST)==0 && idle[i].idle > 60*15) || (!fast && nownum > lowerbound && idle[i].idle > idletimeout ) ) { sprintf(buf, "timeout(%s", ctime4(&SHM->uinfo[which].lastact)); buf[strlen(buf) - 1] = 0; strcat(buf, ")"); clean = buf; addkilllist(which); purge_utmp(&SHM->uinfo[which]); printf("%s\n", buf); --nownum; continue; } #endif if( clean ){ printf("clean %06d(%s), userid: %s\n", i, clean, SHM->uinfo[which].userid); memset(&SHM->uinfo[which], 0, sizeof(userinfo_t)); --nownum; changeflag = 1; } } for( i = 0 ; i < killtop ; ++i ){ printf("sending SIGHUP to %d\n", (int)killlist[i].pid); kill(killlist[i].pid, SIGHUP); } sleep(3); for( i = 0 ; i < killtop ; ++i ) // FIXME 前面已經 memset 把 SHM->uinfo[which] 清掉了, 此處檢查 pid 無用 if( SHM->uinfo[killlist[i].where].pid == killlist[i].pid && kill(killlist[i].pid, 0) == 0 ){ // still alive printf("sending SIGKILL to %d\n", (int)killlist[i].pid); kill(killlist[i].pid, SIGKILL); purge_utmp(&SHM->uinfo[killlist[i].where]); } SHM->UTMPbusystate = 0; if( changeflag ) SHM->UTMPneedsort = 1; if( daemonsleep ){ do{ sleep(daemonsleep); } while( upperbound && SHM->UTMPnumber < upperbound ); goto DoUtmpfix; /* XXX: goto */ } return 0; }
struct rspamd_worker * rspamd_fork_worker (struct rspamd_main *rspamd_main, struct rspamd_worker_conf *cf, guint index, struct event_base *ev_base) { struct rspamd_worker *wrk; gint rc; struct rlimit rlim; /* Starting worker process */ wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker)); if (!rspamd_socketpair (wrk->control_pipe)) { msg_err ("socketpair failure: %s", strerror (errno)); exit (-errno); } if (!rspamd_socketpair (wrk->srv_pipe)) { msg_err ("socketpair failure: %s", strerror (errno)); exit (-errno); } wrk->srv = rspamd_main; wrk->type = cf->type; wrk->cf = g_malloc (sizeof (struct rspamd_worker_conf)); memcpy (wrk->cf, cf, sizeof (struct rspamd_worker_conf)); wrk->index = index; wrk->ctx = cf->ctx; wrk->pid = fork (); switch (wrk->pid) { case 0: /* Update pid for logging */ rspamd_log_update_pid (cf->type, rspamd_main->logger); /* Remove the inherited event base */ event_reinit (rspamd_main->ev_base); event_base_free (rspamd_main->ev_base); /* Lock statfile pool if possible XXX */ /* Init PRNG after fork */ rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg); rspamd_random_seed_fast (); if (rc != OTTERY_ERR_NONE) { msg_err_main ("cannot initialize PRNG: %d", rc); g_assert (0); } g_random_set_seed (ottery_rand_uint32 ()); /* Drop privilleges */ rspamd_worker_drop_priv (rspamd_main); /* Set limits */ rspamd_worker_set_limits (rspamd_main, cf); /* Re-set stack limit */ getrlimit (RLIMIT_STACK, &rlim); rlim.rlim_cur = 100 * 1024 * 1024; rlim.rlim_max = rlim.rlim_cur; setrlimit (RLIMIT_STACK, &rlim); setproctitle ("%s process", cf->worker->name); rspamd_pidfile_close (rspamd_main->pfh); /* Do silent log reopen to avoid collisions */ rspamd_log_close (rspamd_main->logger); rspamd_log_open (rspamd_main->logger); wrk->start_time = rspamd_get_calendar_ticks (); #if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) # if (GLIB_MINOR_VERSION > 20) /* Ugly hack for old glib */ if (!g_thread_get_initialized ()) { g_thread_init (NULL); } # else g_thread_init (NULL); # endif #endif msg_info_main ("starting %s process %P", cf->worker->name, getpid ()); /* Close parent part of socketpair */ close (wrk->control_pipe[0]); close (wrk->srv_pipe[0]); rspamd_socket_nonblocking (wrk->control_pipe[1]); rspamd_socket_nonblocking (wrk->srv_pipe[1]); /* Execute worker */ cf->worker->worker_start_func (wrk); exit (EXIT_FAILURE); break; case -1: msg_err_main ("cannot fork main process. %s", strerror (errno)); rspamd_pidfile_remove (rspamd_main->pfh); exit (-errno); break; default: /* Close worker part of socketpair */ close (wrk->control_pipe[1]); close (wrk->srv_pipe[1]); rspamd_socket_nonblocking (wrk->control_pipe[0]); rspamd_socket_nonblocking (wrk->srv_pipe[0]); rspamd_srv_start_watching (wrk, ev_base); /* Insert worker into worker's table, pid is index */ g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER ( wrk->pid), wrk); break; } return wrk; }
void ManageSession(struct display *d) { static int pid = 0; Display *dpy; greet_user_rtn greet_stat; #ifdef WITH_CONSOLE_KIT char *ck_session_cookie = NULL; #endif WDMDebug("ManageSession %s\n", d->name); (void)XSetIOErrorHandler(IOErrorHandler); (void)XSetErrorHandler(ErrorHandler); #ifndef HAS_SETPROCTITLE SetTitle(d->name, (char *)0); #else setproctitle("%s", d->name); #endif /* * Load system default Resources */ LoadXloginResources(d); verify.version = 1; greet.version = 1; greet_stat = GreetUser(d, &dpy, &verify, &greet); if (greet_stat == Greet_Success) { clientPid = 0; if (!Setjmp(abortSession)) { (void)Signal(SIGTERM, catchTerm); /* * Start the clients, changing uid/groups * setting up environment and running the session */ #ifdef WITH_CONSOLE_KIT ck_session_cookie = open_ck_session(getpwnam(greet.name), d); #endif if (StartClient(&verify, d, &clientPid, greet.name, greet.password #ifdef WITH_CONSOLE_KIT , ck_session_cookie #endif )) { WDMDebug("Client Started\n"); /* * Wait for session to end, */ for (;;) { if (d->pingInterval) { if (!Setjmp(pingTime)) { (void)Signal(SIGALRM, catchAlrm); (void)alarm(d->pingInterval * 60); pid = wait((waitType *) 0); (void)alarm(0); } else { (void)alarm(0); if (!PingServer(d, (Display *) NULL)) SessionPingFailed(d); } } else { pid = wait((waitType *) 0); } if (pid == clientPid) break; } } else { WDMError("session start failed\n"); } } else { /* * when terminating the session, nuke * the child and then run the reset script */ AbortClient(clientPid); } } #ifdef WITH_CONSOLE_KIT if (ck_session_cookie != NULL) { close_ck_session(ck_session_cookie); free(ck_session_cookie); } #endif /* * run system-wide reset file */ WDMDebug("Source reset program %s\n", d->reset); source(verify.systemEnviron, d->reset); SessionExit(d, OBEYSESS_DISPLAY, TRUE); }
int client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags) { struct sockaddr_un sa; struct stat sb; struct msg_identify_data data; struct winsize ws; size_t size; int fd, fd2, mode; char *name, *term; #ifdef HAVE_SETPROCTITLE char rpathbuf[MAXPATHLEN]; #endif #ifdef HAVE_SETPROCTITLE if (realpath(path, rpathbuf) == NULL) strlcpy(rpathbuf, path, sizeof rpathbuf); setproctitle("client (%s)", rpathbuf); #endif if (lstat(path, &sb) != 0) { if (cmdflags & CMD_STARTSERVER && errno == ENOENT) { if ((fd = server_start(path)) == -1) goto start_failed; goto server_started; } goto not_found; } if (!S_ISSOCK(sb.st_mode)) { errno = ENOTSOCK; goto not_found; } memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); if (size >= sizeof sa.sun_path) { errno = ENAMETOOLONG; goto not_found; } if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("socket"); if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) { if (errno == ECONNREFUSED) { if (unlink(path) != 0 || !(cmdflags & CMD_STARTSERVER)) goto not_found; if ((fd = server_start(path)) == -1) goto start_failed; goto server_started; } goto not_found; } server_started: if ((mode = fcntl(fd, F_GETFL)) == -1) fatal("fcntl failed"); if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) fatal("fcntl failed"); imsg_init(&cctx->ibuf, fd); if (cmdflags & CMD_SENDENVIRON) client_send_environ(cctx); if (isatty(STDIN_FILENO)) { if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) fatal("ioctl(TIOCGWINSZ)"); data.flags = flags; data.sx = ws.ws_col; data.sy = ws.ws_row; if (getcwd(data.cwd, sizeof data.cwd) == NULL) *data.cwd = '\0'; *data.term = '\0'; if ((term = getenv("TERM")) != NULL) { if (strlcpy(data.term, term, sizeof data.term) >= sizeof data.term) *data.term = '\0'; } *data.tty = '\0'; if ((name = ttyname(STDIN_FILENO)) == NULL) fatal("ttyname failed"); if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty) fatalx("ttyname failed"); fd2 = dup(STDIN_FILENO); imsg_compose(&cctx->ibuf, MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd2, &data, sizeof data); } return (0); start_failed: log_warnx("server failed to start"); return (1); not_found: log_warn("server not found"); return (1); }
//----------------------------------------------------------------------------- int main(int argc, char *argv[]) { SETTINGS_IMPL settings; if (argc == 2) { settings.SetConfFile(argv[1]); } else { // Usage } if (settings.ReadSettings()) { printf("ReadSettingsError\n"); printf("%s\n", settings.GetStrError().c_str()); exit(-1); } settings.Print(); if (settings.GetDaemon()) { switch (fork()) { case -1: exit(1); break; case 0: setsid(); break; default: exit(0); break; } } clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalName(), settings.GetLocalPort()); if (!settings.GetNoWeb()) { web = new WEB(); web->SetRefreshPagePeriod(settings.GetRefreshPeriod()); web->SetListenAddr(settings.GetListenWebIP()); web->Start(); } clnp->SetLogin(settings.GetLogin()); clnp->SetPassword(settings.GetPassword()); clnp->SetStatusChangedCb(StatusChanged, NULL); clnp->SetInfoCb(ShowMessage, NULL); clnp->SetErrorCb(ShowError, NULL); clnp->SetDirNameCb(SetDirName, NULL); clnp->SetStatChangedCb(StatUpdate, NULL); clnp->SetReconnect(settings.GetReconnect()); clnp->Start(); SetSignalHandlers(); #ifdef LINUX for (int i = 1; i < argc; i++) memset(argv[i], 0, strlen(argv[i])); if(argc > 1) strcpy(argv[1], "Connecting..."); #endif #ifdef FREEBSD setproctitle("Connecting..."); #endif clnp->Connect(); while (1) { struct timespec ts = {0, 200000000}; nanosleep(&ts, NULL); char state[20]; if (clnp->GetAuthorized()) { if (settings.GetShowPid()) sprintf(state, "On %d", getpid()); else strcpy(state, "Online"); } else { if (settings.GetShowPid()) sprintf(state, "Off %d", getpid()); else strcpy(state, "Offline"); } #ifdef LINUX for (int i = 1; i < argc; i++) memset(argv[i], 0, strlen(argv[i])); if(argc > 1) strcpy(argv[1], state); #endif #ifdef FREEBSD setproctitle(state); #endif #ifdef FREEBSD_5 setproctitle(state); #endif } return 0; }
int main(int argc, char *argv[]) { struct ntpd_conf lconf; struct pollfd pfd[POLL_MAX]; pid_t chld_pid = 0, pid; const char *conffile; int ch, nfds; int pipe_chld[2]; struct passwd *pw; conffile = CONFFILE; bzero(&lconf, sizeof(lconf)); log_init(1); /* log to stderr until daemonized */ while ((ch = getopt(argc, argv, "df:nsSv")) != -1) { switch (ch) { case 'd': lconf.debug = 1; break; case 'f': conffile = optarg; break; case 'n': lconf.noaction = 1; break; case 's': lconf.settime = 1; break; case 'S': lconf.settime = 0; break; case 'v': debugsyslog = 1; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc > 0) usage(); if (parse_config(conffile, &lconf)) exit(1); if (lconf.noaction) { fprintf(stderr, "configuration OK\n"); exit(0); } if (geteuid()) errx(1, "need root privileges"); if ((pw = getpwnam(NTPD_USER)) == NULL) errx(1, "unknown user %s", NTPD_USER); reset_adjtime(); if (!lconf.settime) { log_init(lconf.debug); if (!lconf.debug) if (daemon(1, 0)) fatal("daemon"); } else timeout = SETTIME_TIMEOUT * 1000; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) fatal("socketpair"); signal(SIGCHLD, sighdlr); /* fork child process */ chld_pid = ntp_main(pipe_chld, &lconf, pw); setproctitle("[priv]"); readfreq(); signal(SIGTERM, sighdlr); signal(SIGINT, sighdlr); signal(SIGHUP, sighdlr); close(pipe_chld[1]); if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf, pipe_chld[0]); while (quit == 0) { pfd[PFD_PIPE].fd = ibuf->fd; pfd[PFD_PIPE].events = POLLIN; if (ibuf->w.queued) pfd[PFD_PIPE].events |= POLLOUT; if ((nfds = poll(pfd, 1, timeout)) == -1) if (errno != EINTR) { log_warn("poll error"); quit = 1; } if (nfds == 0 && lconf.settime) { lconf.settime = 0; timeout = INFTIM; log_init(lconf.debug); log_debug("no reply received in time, skipping initial " "time setting"); if (!lconf.debug) if (daemon(1, 0)) fatal("daemon"); } if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) if (msgbuf_write(&ibuf->w) < 0) { log_warn("pipe write error (to child)"); quit = 1; } if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) { nfds--; if (dispatch_imsg(&lconf) == -1) quit = 1; } if (sigchld) { if (check_child(chld_pid, "child")) { quit = 1; chld_pid = 0; } sigchld = 0; } } signal(SIGCHLD, SIG_DFL); if (chld_pid) kill(chld_pid, SIGTERM); do { if ((pid = wait(NULL)) == -1 && errno != EINTR && errno != ECHILD) fatal("wait"); } while (pid != -1 || (pid == -1 && errno == EINTR)); msgbuf_clear(&ibuf->w); free(ibuf); log_info("Terminating"); return (0); }
/* route decision engine */ pid_t rde(struct ripd_conf *xconf, int pipe_parent2rde[2], int pipe_ripe2rde[2], int pipe_parent2ripe[2]) { struct event ev_sigint, ev_sigterm; struct passwd *pw; struct redistribute *r; pid_t pid; switch (pid = fork()) { case -1: fatal("cannot fork"); /* NOTREACHED */ case 0: break; default: return (pid); } rdeconf = xconf; if ((pw = getpwnam(RIPD_USER)) == NULL) fatal("getpwnam"); if (chroot(pw->pw_dir) == -1) fatal("chroot"); if (chdir("/") == -1) fatal("chdir(\"/\")"); setproctitle("route decision engine"); ripd_process = PROC_RDE_ENGINE; if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); event_init(); /* setup signal handler */ signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, rde_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); /* setup pipes */ close(pipe_ripe2rde[0]); close(pipe_parent2rde[0]); close(pipe_parent2ripe[0]); close(pipe_parent2ripe[1]); if ((iev_ripe = malloc(sizeof(struct imsgev))) == NULL || (iev_main = malloc(sizeof(struct imsgev))) == NULL) fatal(NULL); imsg_init(&iev_ripe->ibuf, pipe_ripe2rde[1]); iev_ripe->handler = rde_dispatch_imsg; imsg_init(&iev_main->ibuf, pipe_parent2rde[1]); iev_main->handler = rde_dispatch_parent; /* setup event handler */ iev_ripe->events = EV_READ; event_set(&iev_ripe->ev, iev_ripe->ibuf.fd, iev_ripe->events, iev_ripe->handler, iev_ripe); event_add(&iev_ripe->ev, NULL); iev_main->events = EV_READ; event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, iev_main->handler, iev_main); event_add(&iev_main->ev, NULL); rt_init(); /* remove unneeded config stuff */ while ((r = SIMPLEQ_FIRST(&rdeconf->redist_list)) != NULL) { SIMPLEQ_REMOVE_HEAD(&rdeconf->redist_list, entry); free(r); } event_dispatch(); rde_shutdown(); /* NOTREACHED */ return (0); }
/** * Set proctitle. Append cmd in the protitle. * * You should call proc_title_init() to init the proc_title before call * proc_title_set() to append cmd. * * @param cmd */ void proc_title_set(const char *cmd) { setproctitle("%s: %s", proc_title, cmd); }
int main(int argc, char **argv) { char *s, *path, *label, **var, tmp[PATH_MAX]; int opt, flags, keys; #if defined(DEBUG) && defined(__OpenBSD__) malloc_options = (char *) "AFGJPX"; #endif setlocale(LC_TIME, ""); tzset(); if (**argv == '-') flags = CLIENT_LOGIN; else flags = 0; label = path = NULL; while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) { switch (opt) { case '2': flags |= CLIENT_256COLOURS; break; case 'c': free(shell_cmd); shell_cmd = xstrdup(optarg); break; case 'C': if (flags & CLIENT_CONTROL) flags |= CLIENT_CONTROLCONTROL; else flags |= CLIENT_CONTROL; break; case 'V': printf("%s %s\n", __progname, VERSION); exit(0); case 'f': set_cfg_file(optarg); break; case 'l': flags |= CLIENT_LOGIN; break; case 'L': free(label); label = xstrdup(optarg); break; case 'q': break; case 'S': free(path); path = xstrdup(optarg); break; case 'u': flags |= CLIENT_UTF8; break; case 'v': debug_level++; break; default: usage(); } } argc -= optind; argv += optind; if (shell_cmd != NULL && argc != 0) usage(); if (!(flags & CLIENT_UTF8)) { /* * If the user has set whichever of LC_ALL, LC_CTYPE or LANG * exist (in that order) to contain UTF-8, it is a safe * assumption that either they are using a UTF-8 terminal, or * if not they know that output from UTF-8-capable programs may * be wrong. */ if ((s = getenv("LC_ALL")) == NULL || *s == '\0') { if ((s = getenv("LC_CTYPE")) == NULL || *s == '\0') s = getenv("LANG"); } if (s != NULL && (strcasestr(s, "UTF-8") != NULL || strcasestr(s, "UTF8") != NULL)) flags |= CLIENT_UTF8; } environ_init(&global_environ); for (var = environ; *var != NULL; var++) environ_put(&global_environ, *var); if (getcwd(tmp, sizeof tmp) != NULL) environ_set(&global_environ, "PWD", tmp); options_init(&global_options, NULL); options_table_populate_tree(server_options_table, &global_options); options_init(&global_s_options, NULL); options_table_populate_tree(session_options_table, &global_s_options); options_set_string(&global_s_options, "default-shell", "%s", getshell()); options_init(&global_w_options, NULL); options_table_populate_tree(window_options_table, &global_w_options); /* Enable UTF-8 if the first client is on UTF-8 terminal. */ if (flags & CLIENT_UTF8) { options_set_number(&global_s_options, "status-utf8", 1); options_set_number(&global_s_options, "mouse-utf8", 1); options_set_number(&global_w_options, "utf8", 1); } /* Override keys to vi if VISUAL or EDITOR are set. */ if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) { if (strrchr(s, '/') != NULL) s = strrchr(s, '/') + 1; if (strstr(s, "vi") != NULL) keys = MODEKEY_VI; else keys = MODEKEY_EMACS; options_set_number(&global_s_options, "status-keys", keys); options_set_number(&global_w_options, "mode-keys", keys); } /* * Figure out the socket path. If specified on the command-line with -S * or -L, use it, otherwise try $TMUX or assume -L default. */ if (path == NULL) { /* If no -L, use the environment. */ if (label == NULL) { s = getenv("TMUX"); if (s != NULL) { path = xstrdup(s); path[strcspn (path, ",")] = '\0'; if (*path == '\0') { free(path); label = xstrdup("default"); } } else label = xstrdup("default"); } /* -L or default set. */ if (label != NULL) { if ((path = makesocketpath(label)) == NULL) { fprintf(stderr, "can't create socket: %s\n", strerror(errno)); exit(1); } } } free(label); if (strlcpy(socket_path, path, sizeof socket_path) >= sizeof socket_path) { fprintf(stderr, "socket path too long: %s\n", path); exit(1); } free(path); #ifdef HAVE_SETPROCTITLE /* Set process title. */ setproctitle("%s (%s)", __progname, socket_path); #endif /* Pass control to the client. */ exit(client_main(osdep_event_init(), argc, argv, flags)); }
static void tls_exec_client(const char *user, int startfd, const char *srcaddr, const char *dstaddr, const char *fingerprint, const char *defport, int timeout, int debuglevel) { struct proto_conn *tcp; char *saddr, *daddr; SSL_CTX *sslctx; SSL *ssl; long ret; int sockfd, tcpfd; uint8_t connected; pjdlog_debug_set(debuglevel); pjdlog_prefix_set("[TLS sandbox] (client) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (client) "); #endif proto_set("tcp:port", defport); sockfd = startfd; /* Change tls:// to tcp://. */ if (srcaddr == NULL) { saddr = NULL; } else { saddr = strdup(srcaddr); if (saddr == NULL) pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); bcopy("tcp://", saddr, 6); } daddr = strdup(dstaddr); if (daddr == NULL) pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory."); bcopy("tcp://", daddr, 6); /* Establish TCP connection. */ if (proto_connect(saddr, daddr, timeout, &tcp) == -1) exit(EX_TEMPFAIL); SSL_load_error_strings(); SSL_library_init(); /* * TODO: On FreeBSD we could move this below sandbox() once libc and * libcrypto use sysctl kern.arandom to obtain random data * instead of /dev/urandom and friends. */ sslctx = SSL_CTX_new(TLSv1_client_method()); if (sslctx == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed."); if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0) pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client."); pjdlog_debug(1, "Privileges successfully dropped."); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* Load CA certs. */ /* TODO */ //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL); ssl = SSL_new(sslctx); if (ssl == NULL) pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed."); tcpfd = proto_descriptor(tcp); block(tcpfd); if (SSL_set_fd(ssl, tcpfd) != 1) pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed."); ret = SSL_connect(ssl); ssl_check_error(ssl, (int)ret); nonblock(sockfd); nonblock(tcpfd); tls_certificate_verify(ssl, fingerprint); /* * The following byte is send to make proto_connect_wait() to work. */ connected = 1; for (;;) { switch (send(sockfd, &connected, sizeof(connected), 0)) { case -1: if (errno == EINTR || errno == ENOBUFS) continue; if (errno == EAGAIN) { (void)wait_for_fd(sockfd, -1); continue; } pjdlog_exit(EX_TEMPFAIL, "send() failed"); case 0: pjdlog_debug(1, "Connection terminated."); exit(0); case 1: break; } break; } tls_loop(sockfd, ssl); }
/* * Periodically test network connection. On signals, determine what * happened or what to do with child. Return as necessary for exit * or restart of child. */ int ssh_watch(int sock) { int r; int val; static int secs_left; int my_poll_time = first_poll_time; time_t now; double secs_to_shutdown; #if defined(HAVE_SETPROCTITLE) setproctitle("parent of %d (%d)", (int)cchild, start_count); #endif for (;;) { if (restart_ssh) { errlog(LOG_INFO, "signalled to kill and restart ssh"); ssh_kill(); return P_RESTART; } if ((val = sigsetjmp(jumpbuf, 1)) == 0) { errlog(LOG_DEBUG, "check on child %d", cchild); /* poll for expired child */ r = ssh_wait(WNOHANG); if (r != P_CONTINUE) { errlog(LOG_DEBUG, "expired child, returning %d", r); return r; } secs_left = alarm(0); if (secs_left == 0) secs_left = my_poll_time; my_poll_time = poll_time; if (max_lifetime != 0) { time(&now); secs_to_shutdown = max_lifetime - difftime(now,pid_start_time); if (secs_to_shutdown < poll_time) secs_left = secs_to_shutdown; } errlog(LOG_DEBUG, "set alarm for %d secs", secs_left); alarm(secs_left); dolongjmp = 1; pause(); } else { switch(val) { case SIGINT: case SIGTERM: case SIGQUIT: case SIGABRT: errlog(LOG_INFO, "received signal to exit (%d)", val); ssh_kill(); return P_EXIT; break; case SIGALRM: if (exceeded_lifetime()) { ssh_kill(); return P_EXIT; } if (writep && sock != -1 && !conn_test(sock, mhost, writep)) { errlog(LOG_INFO, "port down, restarting ssh"); ssh_kill(); return P_RESTART; } #ifdef TOUCH_PIDFILE /* * utimes() with a NULL time argument sets * file access and modification times to * the current time */ if (pid_file_name && utimes(pid_file_name, NULL) != 0) { errlog(LOG_ERR, "could not touch pid file: %s", strerror(errno)); } #endif break; default: break; } } } }
static int tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct tls_ctx *tlsctx; struct proto_conn *sock; pid_t pid; int error; PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); PJDLOG_ASSERT(ctxp != NULL); if (strncmp(dstaddr, "tls://", 6) != 0) return (-1); if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0) return (-1); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); #if 0 /* * We use rfork() with the following flags to disable SIGCHLD * delivery upon the sandbox process exit. */ pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0)); #else /* * We don't use rfork() to be able to log information about sandbox * process exiting. */ pid = fork(); #endif switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (client) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (client) "); #endif tls_call_exec_client(sock, srcaddr, dstaddr, timeout); /* NOTREACHED */ default: /* Parent. */ tlsctx = calloc(1, sizeof(*tlsctx)); if (tlsctx == NULL) { error = errno; proto_close(sock); (void)kill(pid, SIGKILL); return (error); } proto_send(sock, NULL, 0); tlsctx->tls_sock = sock; tlsctx->tls_tcp = NULL; tlsctx->tls_side = TLS_SIDE_CLIENT; tlsctx->tls_wait_called = false; tlsctx->tls_magic = TLS_CTX_MAGIC; if (timeout >= 0) { error = tls_connect_wait(tlsctx, timeout); if (error != 0) { (void)kill(pid, SIGKILL); tls_close(tlsctx); return (error); } } *ctxp = tlsctx; return (0); } }
/*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); 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); } #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 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); }
static int tls_accept(void *ctx, void **newctxp) { struct tls_ctx *tlsctx = ctx; struct tls_ctx *newtlsctx; struct proto_conn *sock, *tcp; pid_t pid; int error; PJDLOG_ASSERT(tlsctx != NULL); PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC); PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); /* Accept TCP connection. */ if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) { error = errno; proto_close(sock); return (error); } pid = fork(); switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (server) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (server) "); #endif /* Close listen socket. */ proto_close(tlsctx->tls_tcp); tls_call_exec_server(sock, tcp); /* NOTREACHED */ PJDLOG_ABORT("Unreachable."); default: /* Parent. */ newtlsctx = calloc(1, sizeof(*tlsctx)); if (newtlsctx == NULL) { error = errno; proto_close(sock); proto_close(tcp); (void)kill(pid, SIGKILL); return (error); } proto_local_address(tcp, newtlsctx->tls_laddr, sizeof(newtlsctx->tls_laddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_laddr, 6); *strrchr(newtlsctx->tls_laddr, ':') = '\0'; proto_remote_address(tcp, newtlsctx->tls_raddr, sizeof(newtlsctx->tls_raddr)); PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0); bcopy("tls://", newtlsctx->tls_raddr, 6); *strrchr(newtlsctx->tls_raddr, ':') = '\0'; proto_close(tcp); proto_recv(sock, NULL, 0); newtlsctx->tls_sock = sock; newtlsctx->tls_tcp = NULL; newtlsctx->tls_wait_called = true; newtlsctx->tls_side = TLS_SIDE_SERVER_WORK; newtlsctx->tls_magic = TLS_CTX_MAGIC; *newctxp = newtlsctx; return (0); } }
/* * Performs authentication of an incoming connection. Session key has already * been exchanged and encryption is enabled. */ void do_authentication(Authctxt *authctxt) { u_int ulen; char *user, *style = NULL, *role = NULL; /* Get the name of the user that we wish to log in as. */ packet_read_expect(SSH_CMSG_USER); /* Get the user name. */ user = packet_get_cstring(&ulen); packet_check_eom(); if ((role = strchr(user, '/')) != NULL) *role++ = '\0'; if ((style = strchr(user, ':')) != NULL) *style++ = '\0'; else if (role && (style = strchr(role, ':')) != NULL) *style++ = '\0'; authctxt->user = user; authctxt->style = style; authctxt->role = role; /* Verify that the user is a valid user. */ if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) authctxt->valid = 1; else { debug("do_authentication: invalid user %s", user); authctxt->pw = fakepw(); } setproctitle("%s%s", authctxt->valid ? user : "******", use_privsep ? " [net]" : ""); #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(authctxt)); #endif /* * If we are not running as root, the user must have the same uid as * the server. */ #ifndef HAVE_CYGWIN if (!use_privsep && getuid() != 0 && authctxt->pw && authctxt->pw->pw_uid != getuid()) packet_disconnect("Cannot change user when server not running as root."); #endif /* * Loop until the user has been authenticated or the connection is * closed, do_authloop() returns only if authentication is successful */ do_authloop(authctxt); /* The user has been authenticated and accepted. */ packet_start(SSH_SMSG_SUCCESS); packet_send(); packet_write_wait(); }
pid_t proc_run(struct privsep *ps, struct privsep_proc *p, struct privsep_proc *procs, unsigned int nproc, void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg) { pid_t pid; struct passwd *pw; const char *root; struct control_sock *rcs; unsigned int n; if (ps->ps_noaction) return (0); proc_open(ps, p, procs, nproc); /* Fork child handlers */ switch (pid = fork()) { case -1: fatal("proc_run: cannot fork"); case 0: log_procinit(p->p_title); /* Set the process group of the current process */ setpgid(0, 0); break; default: return (pid); } pw = ps->ps_pw; if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) { if (control_init(ps, &ps->ps_csock) == -1) fatalx(__func__); TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry) if (control_init(ps, rcs) == -1) fatalx(__func__); } /* Change root directory */ if (p->p_chroot != NULL) root = p->p_chroot; else root = pw->pw_dir; if (chroot(root) == -1) fatal("proc_run: chroot"); if (chdir("/") == -1) fatal("proc_run: chdir(\"/\")"); privsep_process = p->p_id; setproctitle("%s", p->p_title); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("proc_run: cannot drop privileges"); /* Fork child handlers */ for (n = 1; n < ps->ps_instances[p->p_id]; n++) { if (fork() == 0) { ps->ps_instance = p->p_instance = n; break; } } #ifdef DEBUG log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title, ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid()); #endif event_init(); signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p); signal_set(&ps->ps_evsigterm, SIGTERM, proc_sig_handler, p); signal_set(&ps->ps_evsigchld, SIGCHLD, proc_sig_handler, p); signal_set(&ps->ps_evsighup, SIGHUP, proc_sig_handler, p); signal_set(&ps->ps_evsigpipe, SIGPIPE, proc_sig_handler, p); signal_set(&ps->ps_evsigusr1, SIGUSR1, proc_sig_handler, p); signal_add(&ps->ps_evsigint, NULL); signal_add(&ps->ps_evsigterm, NULL); signal_add(&ps->ps_evsigchld, NULL); signal_add(&ps->ps_evsighup, NULL); signal_add(&ps->ps_evsigpipe, NULL); signal_add(&ps->ps_evsigusr1, NULL); proc_listen(ps, procs, nproc); if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) { TAILQ_INIT(&ctl_conns); if (control_listen(&ps->ps_csock) == -1) fatalx(__func__); TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry) if (control_listen(rcs) == -1) fatalx(__func__); }
static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode) { int ret = -1, pid, start_pipe[2]; ssize_t count; bool success = false; CriuResp resp = CRIU_RESP__INIT; CriuPageServerInfo ps = CRIU_PAGE_SERVER_INFO__INIT; struct ps_info info; if (pipe(start_pipe)) { pr_perror("No start pipe"); goto out; } pid = fork(); if (pid == 0) { close(start_pipe[0]); if (setup_opts_from_req(sk, req)) goto out_ch; setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.port); pr_debug("Starting page server\n"); pid = cr_page_server(daemon_mode, false, start_pipe[1]); if (pid < 0) goto out_ch; if (daemon_mode) { info.pid = pid; info.port = opts.port; count = write(start_pipe[1], &info, sizeof(info)); if (count != sizeof(info)) goto out_ch; } ret = 0; out_ch: if (daemon_mode && ret < 0 && pid > 0) kill(pid, SIGKILL); close(start_pipe[1]); exit(ret); } close(start_pipe[1]); if (daemon_mode) { if (waitpid(pid, &ret, 0) != pid) { pr_perror("Unable to wait %d", pid); goto out; } if (WIFEXITED(ret)) { if (WEXITSTATUS(ret)) { pr_err("Child exited with an error\n"); goto out; } } else { pr_err("Child wasn't terminated normally\n"); goto out; } } count = read(start_pipe[0], &info, sizeof(info)); close(start_pipe[0]); if (count != sizeof(info)) goto out; ps.pid = info.pid; ps.has_port = true; ps.port = info.port; success = true; ps.has_pid = true; resp.ps = &ps; pr_debug("Page server started\n"); out: resp.type = CRIU_REQ_TYPE__PAGE_SERVER; resp.success = success; return send_criu_msg(sk, &resp); }
int main(int argc, char *argv[]) { ni_status status; ni_name myname = argv[0]; int create = 0; int log_pri = LOG_NOTICE; ni_name dbsource_name = NULL; ni_name dbsource_addr = NULL; ni_name dbsource_tag = NULL; struct rlimit rlim; char *str; unsigned db_checksum; FILE *logf; int nctoken; logf = NULL; forcedIsRoot = 0; Argv = argv; /* Save program and argument information for setproctitle */ Argc = argc; argc--; argv++; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-d") == 0) { debug = 1; log_pri = LOG_DEBUG; if (argc < 2) logf = stderr; else { debug = atoi(argv[1]); argc -= 1; argv += 1; } } else if (strcmp(*argv, "-l") == 0) { if (argc < 2) usage(myname); else { log_pri = atoi(argv[1]); argc -= 1; argv += 1; } } else if (strcmp(*argv, "-n") == 0) forcedIsRoot = 1; else if (strcmp(*argv, "-s") == 0) standalone = 1; else if (strcmp(*argv, "-m") == 0) create++; else if (strcmp(*argv, "-c") == 0) { if (argc < 4) usage(myname); create++; dbsource_name = argv[1]; dbsource_addr = argv[2]; dbsource_tag = argv[3]; argc -= 3; argv += 3; } else usage(myname); argc--; argv++; } if (argc != 1) usage(myname); if (debug == 0) { closeall(); if (standalone == 1) daemon(1, 1); } db_tag = malloc(strlen(argv[0]) + 1); strcpy(db_tag, argv[0]); str = malloc(strlen("netinfod ") + strlen(db_tag) + 1); sprintf(str, "netinfod %s", db_tag); system_log_open(str, (LOG_NDELAY | LOG_PID), LOG_NETINFO, logf); free(str); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s (pid %d) - starting", _PROJECT_VERSION_, getpid()); rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max = FD_SETSIZE; setrlimit(RLIMIT_NOFILE, &rlim); umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); srandom(gethostid() ^ time(NULL)); readall_syslock = syslock_new(0); lockup_syslock= syslock_new(0); cleanupwait = CLEANUPWAIT; auth_count[GOOD] = 0; auth_count[BAD] = 0; auth_count[WGOOD] = 0; auth_count[WBAD] = 0; if (create) { if (dbsource_addr == NULL) { system_log(LOG_DEBUG, "creating master"); status = dir_mastercreate(db_tag); } else { system_log(LOG_DEBUG, "creating clone"); status = dir_clonecreate(db_tag, dbsource_name, dbsource_addr, dbsource_tag); } if (status != NI_OK) { system_log_close(); exit(status); } } nctoken = -1; notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken); if (standalone == 0) signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, (void *)catch_sighup); signal(SIGCHLD, (void *)readall_catcher); if (debug == 0) { signal(SIGINT, (void *)dblock_catcher); if (standalone == 0) { if (setsid() < 0) syslog(LOG_WARNING, "setsid failed: %m"); } } writepid(db_tag); status = start_service(db_tag); if (status != NI_OK) { system_log(LOG_ERR, "start_service failed: %s - exiting", ni_error(status)); system_log_close(); exit(status); } setproctitle("netinfod %s (%s)", db_tag, i_am_clone ? "clone" : "master"); if (i_am_clone) { system_log(LOG_DEBUG, "checking clone"); cloneReadallResponseOK = get_clone_readall(db_ni); dir_clonecheck(); if (get_sanitycheck(db_ni)) sanitycheck(db_tag); system_log(LOG_DEBUG, "finished clone check"); } else { system_log(LOG_DEBUG, "setting up master server"); promote_admins = get_promote_admins(db_ni); get_readall_info(db_ni, &max_readall_proxies, &strict_proxies); max_subthreads = get_max_subthreads(db_ni); update_latency_secs = get_update_latency(db_ni); /* Tracking readall proxy pids uses ObjC, so isolate it */ initialize_readall_proxies(-1 == max_readall_proxies ? MAX_READALL_PROXIES : max_readall_proxies); system_log(LOG_DEBUG, "starting notify thread"); (void) notify_start(); } /* Shutdown gracefully after this point */ if (standalone == 1) signal(SIGTERM, (void *)sig_shutdown); signal(SIGUSR1, (void *)sig_shutdown); system_log(LOG_DEBUG, "starting RPC service"); ni_svc_run(_rpc_dtablesize() - (FD_SLOPSIZE + max_subthreads)); system_log(LOG_DEBUG, "shutting down"); /* * Tell the readall proxies to shut down */ if (readall_proxies > 0) { system_log(LOG_INFO, "killing %d readall prox%s", readall_proxies, 1 == readall_proxies ? "y" : "ies"); if (!kill_proxies()) system_log(LOG_WARNING, "some readall proxies still running"); } db_checksum = ni_getchecksum(db_ni); ni_shutdown(db_ni, db_checksum); system_log(LOG_INFO, "exiting; checksum %u", db_checksum); system_log_close(); exit(0); }
void set_proc_title(const char *format, ...) { va_list ap; #ifndef PS_USE_NONE #ifdef PS_USE_CLOBBER_ARGV /* If ps_buffer is a pointer, it might still be null */ if (!ps_buffer) return; #endif /* Update ps_buffer to contain both fixed part and activity */ va_start(ap, format); vsnprintf(ps_buffer + ps_buffer_fixed_size, ps_buffer_size - ps_buffer_fixed_size, format, ap); va_end(ap); /* Transmit new setting to kernel, if necessary */ #ifdef PS_USE_SETPROCTITLE setproctitle("%s", ps_buffer); #endif #ifdef PS_USE_PSTAT { union pstun pst; pst.pst_command = ps_buffer; pstat(PSTAT_SETCMD, pst, strlen(ps_buffer), 0, 0); } #endif /* PS_USE_PSTAT */ #ifdef PS_USE_PS_STRINGS PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = ps_buffer; #endif /* PS_USE_PS_STRINGS */ #ifdef PS_USE_CLOBBER_ARGV { int buflen; /* pad unused memory */ buflen = strlen(ps_buffer); /* clobber remainder of old status string */ if (last_status_len > buflen) memset(ps_buffer + buflen, PS_PADDING, last_status_len - buflen); last_status_len = buflen; } #endif /* PS_USE_CLOBBER_ARGV */ #ifdef PS_USE_WIN32 { /* * Win32 does not support showing any changed arguments. To make it at * all possible to track which backend is doing what, we create a * named object that can be viewed with for example Process Explorer. */ static HANDLE ident_handle = INVALID_HANDLE_VALUE; char name[PS_BUFFER_SIZE + 32]; if (ident_handle != INVALID_HANDLE_VALUE) CloseHandle(ident_handle); sprintf(name, "pgident(%d): %s", MyProcPid, ps_buffer); ident_handle = CreateEvent(NULL, TRUE, FALSE, name); } #endif /* PS_USE_WIN32 */ #endif /* not PS_USE_NONE */ }
void vsf_sysutil_setproctitle_internal(const char* p_buf) { setproctitle("%s", p_buf); }
int main (int argc, char **argv) { const char *progname = NULL; const char *script = NULL; int child_status = 0; size_t i; array_init (&new_argv); set_sig_handler (); /* discard runawk's own ARGV[0] */ --argc, ++argv; if (argc == 0) { usage (); return 30; } /* cwd */ if (!getcwd (cwd, sizeof (cwd))) { perror ("runawk: getcwd (3) failed"); die (32); } array_pushdup (&new_argv, NULL); /* will fill in progname later */ if (AWK2) { array_pushdup (&new_argv, AWK2); } /* need to parse a run-together shebang line? */ if (argc >= 2 && argv [0][0] == '-' && argv[1][0] != '-' && strchr(argv[0], ' ')) { shebang.argc = --argc; shebang.argv = ++argv; array_init (&shebang.array); char *p; char *token = argv[-1]; for (p = token; *p; ) { if (*p == ' ') { *p++ = 0; array_pushdup(&shebang.array, token); token = p; } else { p++; } } if (p > token) { array_pushdup(&shebang.array, token); } argc = shebang.array.size; argv = (char **) shebang.array.contents; } else { shebang.argc = 0; } /* parse options manually */ for (; argc && argv [0][0] == '-'; --argc, ++argv) { /* --help */ if (!strcmp (argv [0], "--help")) { usage (); die (0); } /* --version */ if (!strcmp (argv [0], "--version")) { version (); die (0); } /* --stdin */ if (!strcmp (argv [0], "--stdin")) { add_stdin = 1; continue; } /* -F <FS>*/ if (!strcmp (argv [0], "-F")) { if (argc == 1) { fprintf (stderr, "runawk: missing argument for -F option\n"); die (39); } array_pushdup (&new_argv, "-F"); array_pushdup (&new_argv, argv [1]); --argc; ++argv; continue; } /* -F<FS>*/ if (!strncmp (argv [0], "-F", 2)) { array_pushdup (&new_argv, "-F"); array_pushdup (&new_argv, argv [0]+2); continue; } /* -v|--assign <VAR=VALUE> */ if (!strcmp (argv [0], "-v") || !strcmp (argv [0], "--assign")) { if (argc == 1) { fprintf (stderr, "runawk: missing argument for -v option\n"); die (39); } array_pushdup (&new_argv, "-v"); array_pushdup (&new_argv, argv [1]); --argc; ++argv; continue; } /* -v<VAR=VALUE> */ if (!strncmp (argv [0], "-v", 2)) { array_pushdup (&new_argv, "-v"); array_pushdup (&new_argv, argv [0]+2); continue; } /* -f|--file <FILE> */ if (!strcmp (argv [0], "-f") || !strcmp (argv [0], "--file")) { if (argc == 1) { fprintf (stderr, "runawk: missing argument for -f option\n"); die (39); } add_file (cwd, argv [1], 0); --argc; ++argv; continue; } /* -f<FILE> */ if (!strncmp (argv [0], "-f", 2)) { add_file (cwd, argv [0]+2, 0); continue; } /* -e|--source <PROGRAM TEXT> */ if (!strcmp (argv [0], "-e") || !strcmp (argv [0], "--source")) { if (argc == 1) { fprintf (stderr, "runawk: missing argument for -e option\n"); die (39); } script = argv [1]; --argc; ++argv; continue; } /* -e<PROGRAM TEXT> */ if (!strncmp (argv [0], "-e", 2)) { script = argv [0]+2; continue; } if (!strcmp (argv [0], "--exec")) { if (shebang.argc) { if (script) { fprintf (stderr, "runawk: --exec conflicts with --source\n"); die (39); } execing = 1; // add_file(cwd, shebang.argv [0], 1); // ++shebang.argv; // --shebang.argc; --argc; ++argv; break; } if (argc == 1) { fprintf (stderr, "runawk: missing argument for --exec option\n"); die (39); } execing = 1; // add_file (cwd, argv [1], 1); --argc; ++argv; break; } /* -- */ if (!strcmp (argv [0], "--")) { --argc; ++argv; break; } /* --unknown */ if (!strncmp (argv [0], "--", 2)) { array_pushdup (&new_argv, argv [0]); continue; } /* -x etc */ if (argv[0][1]) { fprintf (stderr, "runawk: unknown option -%c\n", *(argv [0]+1)); die (1); } /* - */ break; } if (shebang.argc) { if (argc) { fprintf (stderr, "runawk: can't parse shebang line: %s\n", argv[0]); die (1); } array_free (&shebang.array); argv = shebang.argv; argc = shebang.argc; } progname = interpreter; if (script) { add_buffer (script, strlen (script)); } else { /* program_file */ if (argc < 1) { usage (); die (30); } --argc; add_file (cwd, *argv, execing); progname = *argv; #if 0 setprogname (*argv); setproctitle (*argv); #endif ++argv; } /* exec */ new_argv.contents [0] = xstrdup (progname); if (files && !execing) array_pushdup (&new_argv, "--"); for (i=0; i < (size_t) argc; ++i) { array_pushdup (&new_argv, argv [i]); } if (add_stdin) { array_pushdup (&new_argv, "/dev/stdin"); } array_pushdup (&new_argv, NULL); awk_pid = fork (); switch (awk_pid) { case -1: perror ("runawk: fork(2) failed"); die (42); break; case 0: /* child */ execvp (interpreter, (char *const *) new_argv.contents); fprintf (stderr, "runawk: running '%s' failed: %s\n", interpreter, strerror (errno)); exit (1); break; default: /* parent */ waitpid (-1, &child_status, 0); array_free (&new_argv); if (killing_sig) { die (0); } else if (WIFSIGNALED (child_status)) { die (128 + WTERMSIG (child_status)); } else if (WIFEXITED (child_status)) { die (WEXITSTATUS (child_status)); } else { die (200); } } die (0); return 0; /* this should not happen but fixes gcc warning */ }
pid_t control(void) { struct sockaddr_un sun; int fd; mode_t old_umask; pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; struct peer peers [] = { { PROC_SCHEDULER, imsg_dispatch }, { PROC_QUEUE, imsg_dispatch }, { PROC_SMTP, imsg_dispatch }, { PROC_MFA, imsg_dispatch }, { PROC_PARENT, imsg_dispatch }, { PROC_LKA, imsg_dispatch }, { PROC_MDA, imsg_dispatch }, { PROC_MTA, imsg_dispatch } }; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: break; default: return (pid); } purge_config(PURGE_EVERYTHING); pw = env->sc_pw; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("control: socket"); bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; if (strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) fatal("control: socket name too long"); if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) fatalx("control socket already listening"); if (unlink(SMTPD_SOCKET) == -1) if (errno != ENOENT) fatal("control: cannot unlink socket"); old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { (void)umask(old_umask); fatal("control: bind"); } (void)umask(old_umask); if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { (void)unlink(SMTPD_SOCKET); fatal("control: chmod"); } session_socket_blockmode(fd, BM_NONBLOCK); control_state.fd = fd; stat_backend = env->sc_stat; stat_backend->init(); if (chroot(pw->pw_dir) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); smtpd_process = PROC_CONTROL; setproctitle("%s", env->sc_title[smtpd_process]); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); TAILQ_INIT(&ctl_conns); config_pipes(peers, nitems(peers)); config_peers(peers, nitems(peers)); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }
/*ARGSUSED*/ static int 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); 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); } /* 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); return 0; }
/* * Performs authentication of an incoming connection. Session key has already * been exchanged and encryption is enabled. */ Authctxt * do_authentication(void) { Authctxt *authctxt; u_int ulen; char *user, *style = NULL; /* Get the name of the user that we wish to log in as. */ packet_read_expect(SSH_CMSG_USER); /* Get the user name. */ user = packet_get_string(&ulen); packet_check_eom(); if ((style = strchr(user, ':')) != NULL) *style++ = '\0'; #ifdef KRB5 /* XXX - SSH.com Kerberos v5 braindeath. */ if ((datafellows & SSH_BUG_K5USER) && options.kerberos_authentication) { char *p; if ((p = strchr(user, '@')) != NULL) *p = '\0'; } #endif authctxt = authctxt_new(); authctxt->user = user; authctxt->style = style; /* Verify that the user is a valid user. */ if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) authctxt->valid = 1; else debug("do_authentication: illegal user %s", user); setproctitle("%s%s", authctxt->pw ? user : "******", use_privsep ? " [net]" : ""); #ifdef USE_PAM PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user)); #endif /* * If we are not running as root, the user must have the same uid as * the server. (Unless you are running Windows) */ #ifndef HAVE_CYGWIN if (!use_privsep && getuid() != 0 && authctxt->pw && authctxt->pw->pw_uid != getuid()) packet_disconnect("Cannot change user when server not running as root."); #endif /* * Loop until the user has been authenticated or the connection is * closed, do_authloop() returns only if authentication is successful */ do_authloop(authctxt); /* The user has been authenticated and accepted. */ packet_start(SSH_SMSG_SUCCESS); packet_send(); packet_write_wait(); return (authctxt); }