int main(int argc, char *argv[]) { int opt; int i; int status = 0; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); /* * PRIV_FILE_DAC_READ is needed to read the QFNAME file * Clear all other privleges from the limit set, and add * the required privilege to the bracketed set. */ if (__init_suid_priv(PU_CLEARLIMITSET, PRIV_FILE_DAC_READ, NULL) == -1) { (void) fprintf(stderr, gettext("Insufficient privileges, " "quota must be set-uid root or have " "file_dac_read privileges\n")); exit(1); } load_libzfs(); while ((opt = getopt(argc, argv, "vV")) != EOF) { switch (opt) { case 'v': vflag++; break; case 'V': /* Print command line */ { char *opt_text; int opt_count; (void) fprintf(stdout, "quota -F UFS "); for (opt_count = 1; opt_count < argc; opt_count++) { opt_text = argv[opt_count]; if (opt_text) (void) fprintf(stdout, " %s ", opt_text); } (void) fprintf(stdout, "\n"); } break; case '?': fprintf(stderr, "usage: quota [-v] [username]\n"); zexit(32); } } if (quotactl(Q_ALLSYNC, NULL, (uid_t)0, NULL) < 0 && errno == EINVAL) { if (vflag) fprintf(stderr, "There are no quotas on this system\n"); nolocalquota++; } if (argc == optind) { showuid(getuid()); zexit(0); } for (i = optind; i < argc; i++) { if (alldigits(argv[i])) { showuid((uid_t)atoi(argv[i])); } else status |= showname(argv[i]); } __priv_relinquish(); return (status); }
int main(int argc, char *argv[]) { struct utmpx *ut; struct utmpx *utmpbegin; struct utmpx *utmpend; struct utmpx *utp; struct uproc *up, *parent, *pgrp; struct psinfo info; struct sigaction actinfo[ACTSIZE]; struct pstatus statinfo; size_t size; struct stat sbuf; DIR *dirp; struct dirent *dp; char pname[64]; char *fname; int procfd; char *cp; int i; int days, hrs, mins; int entries; double loadavg[3]; /* * This program needs the proc_owner privilege */ (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER, (char *)NULL); (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); login = (argv[0][0] == '-'); cp = strrchr(argv[0], '/'); firstchar = login ? argv[0][1] : (cp == 0) ? argv[0][0] : cp[1]; prog = argv[0]; while (argc > 1) { if (argv[1][0] == '-') { for (i = 1; argv[1][i]; i++) { switch (argv[1][i]) { case 'h': header = 0; break; case 'l': lflag++; break; case 's': lflag = 0; break; case 'u': case 'w': firstchar = argv[1][i]; break; default: (void) fprintf(stderr, gettext( "%s: bad flag %s\n"), prog, argv[1]); exit(1); } } } else { if (!isalnum(argv[1][0]) || argc > 2) { (void) fprintf(stderr, gettext( "usage: %s [ -hlsuw ] [ user ]\n"), prog); exit(1); } else sel_user = argv[1]; } argc--; argv++; } /* * read the UTMPX_FILE (contains information about each logged in user) */ if (stat(UTMPX_FILE, &sbuf) == ERR) { (void) fprintf(stderr, gettext("%s: stat error of %s: %s\n"), prog, UTMPX_FILE, strerror(errno)); exit(1); } entries = sbuf.st_size / sizeof (struct futmpx); size = sizeof (struct utmpx) * entries; if ((ut = malloc(size)) == NULL) { (void) fprintf(stderr, gettext("%s: malloc error of %s: %s\n"), prog, UTMPX_FILE, strerror(errno)); exit(1); } (void) utmpxname(UTMPX_FILE); utmpbegin = ut; utmpend = (struct utmpx *)((char *)utmpbegin + size); setutxent(); while ((ut < utmpend) && ((utp = getutxent()) != NULL)) (void) memcpy(ut++, utp, sizeof (*ut)); endutxent(); (void) time(&now); /* get current time */ if (header) { /* print a header */ prtat(&now); for (ut = utmpbegin; ut < utmpend; ut++) { if (ut->ut_type == USER_PROCESS) { if (!nonuserx(*ut)) nusers++; } else if (ut->ut_type == BOOT_TIME) { uptime = now - ut->ut_xtime; uptime += 30; days = uptime / (60*60*24); uptime %= (60*60*24); hrs = uptime / (60*60); uptime %= (60*60); mins = uptime / 60; PRINTF((gettext("up"))); if (days > 0) PRINTF((gettext( " %d day(s),"), days)); if (hrs > 0 && mins > 0) { PRINTF((" %2d:%02d,", hrs, mins)); } else { if (hrs > 0) PRINTF((gettext( " %d hr(s),"), hrs)); if (mins > 0) PRINTF((gettext( " %d min(s),"), mins)); } } } ut = utmpbegin; /* rewind utmp data */ PRINTF((((nusers == 1) ? gettext(" %d user") : gettext(" %d users")), nusers)); /* * Print 1, 5, and 15 minute load averages. */ (void) getloadavg(loadavg, 3); PRINTF((gettext(", load average: %.2f, %.2f, %.2f\n"), loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN], loadavg[LOADAVG_15MIN])); if (firstchar == 'u') /* uptime command */ exit(0); if (lflag) { PRINTF((dcgettext(NULL, "User tty " "login@ idle JCPU PCPU what\n", LC_TIME))); } else { PRINTF((dcgettext(NULL, "User tty idle what\n", LC_TIME))); } if (fflush(stdout) == EOF) { perror((gettext("%s: fflush failed\n"), prog)); exit(1); } } /* * loop through /proc, reading info about each process * and build the parent/child tree */ if (!(dirp = opendir(PROCDIR))) { (void) fprintf(stderr, gettext("%s: could not open %s: %s\n"), prog, PROCDIR, strerror(errno)); exit(1); } while ((dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.') continue; retry: (void) sprintf(pname, "%s/%s/", PROCDIR, dp->d_name); fname = pname + strlen(pname); (void) strcpy(fname, "psinfo"); if ((procfd = open(pname, O_RDONLY)) < 0) continue; if (read(procfd, &info, sizeof (info)) != sizeof (info)) { int err = errno; (void) close(procfd); if (err == EAGAIN) goto retry; if (err != ENOENT) (void) fprintf(stderr, gettext( "%s: read() failed on %s: %s \n"), prog, pname, strerror(err)); continue; } (void) close(procfd); up = findhash(info.pr_pid); up->p_ttyd = info.pr_ttydev; up->p_state = (info.pr_nlwp == 0? ZOMBIE : RUNNING); up->p_time = 0; up->p_ctime = 0; up->p_igintr = 0; (void) strncpy(up->p_comm, info.pr_fname, sizeof (info.pr_fname)); up->p_args[0] = 0; if (up->p_state != NONE && up->p_state != ZOMBIE) { (void) strcpy(fname, "status"); /* now we need the proc_owner privilege */ (void) __priv_bracket(PRIV_ON); procfd = open(pname, O_RDONLY); /* drop proc_owner privilege after open */ (void) __priv_bracket(PRIV_OFF); if (procfd < 0) continue; if (read(procfd, &statinfo, sizeof (statinfo)) != sizeof (statinfo)) { int err = errno; (void) close(procfd); if (err == EAGAIN) goto retry; if (err != ENOENT) (void) fprintf(stderr, gettext( "%s: read() failed on %s: %s \n"), prog, pname, strerror(err)); continue; } (void) close(procfd); up->p_time = statinfo.pr_utime.tv_sec + statinfo.pr_stime.tv_sec; /* seconds */ up->p_ctime = statinfo.pr_cutime.tv_sec + statinfo.pr_cstime.tv_sec; (void) strcpy(fname, "sigact"); /* now we need the proc_owner privilege */ (void) __priv_bracket(PRIV_ON); procfd = open(pname, O_RDONLY); /* drop proc_owner privilege after open */ (void) __priv_bracket(PRIV_OFF); if (procfd < 0) continue; if (read(procfd, actinfo, sizeof (actinfo)) != sizeof (actinfo)) { int err = errno; (void) close(procfd); if (err == EAGAIN) goto retry; if (err != ENOENT) (void) fprintf(stderr, gettext( "%s: read() failed on %s: %s \n"), prog, pname, strerror(err)); continue; } (void) close(procfd); up->p_igintr = actinfo[SIGINT-1].sa_handler == SIG_IGN && actinfo[SIGQUIT-1].sa_handler == SIG_IGN; /* * Process args. */ up->p_args[0] = 0; clnarglist(info.pr_psargs); (void) strcat(up->p_args, info.pr_psargs); if (up->p_args[0] == 0 || up->p_args[0] == '-' && up->p_args[1] <= ' ' || up->p_args[0] == '?') { (void) strcat(up->p_args, " ("); (void) strcat(up->p_args, up->p_comm); (void) strcat(up->p_args, ")"); } } /* * link pgrp together in case parents go away * Pgrp chain is a single linked list originating * from the pgrp leader to its group member. */ if (info.pr_pgid != info.pr_pid) { /* not pgrp leader */ pgrp = findhash(info.pr_pgid); up->p_pgrpl = pgrp->p_pgrpl; pgrp->p_pgrpl = up; } parent = findhash(info.pr_ppid); /* if this is the new member, link it in */ if (parent->p_upid != INITPROCESS) { if (parent->p_child) { up->p_sibling = parent->p_child; up->p_child = 0; } parent->p_child = up; } } /* revert to non-privileged user after opening */ (void) __priv_relinquish(); (void) closedir(dirp); (void) time(&now); /* get current time */ /* * loop through utmpx file, printing process info * about each logged in user */ for (ut = utmpbegin; ut < utmpend; ut++) { if (ut->ut_type != USER_PROCESS) continue; if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0) continue; /* we're looking for somebody else */ /* print login name of the user */ PRINTF(("%-*.*s ", LOGIN_WIDTH, NMAX, ut->ut_name)); /* print tty user is on */ if (lflag) { PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, ut->ut_line)); } else { if (ut->ut_line[0] == 'p' && ut->ut_line[1] == 't' && ut->ut_line[2] == 's' && ut->ut_line[3] == '/') { PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, &ut->ut_line[4])); } else { PRINTF(("%-*.*s ", LINE_WIDTH, LMAX, ut->ut_line)); } } /* print when the user logged in */ if (lflag) { time_t tim = ut->ut_xtime; prtat(&tim); } /* print idle time */ idle = findidle(ut->ut_line); prttime(idle, 8); showtotals(findhash(ut->ut_pid)); } if (fclose(stdout) == EOF) { perror((gettext("%s: fclose failed"), prog)); exit(1); } return (0); }
int main(int argc, char **argv) { int c; char *cp, *cmd, *name = NULL; struct passwd *pwd; uid_t uid; int options = 0, oldmask; int on = 1; speed_t speed = 0; int getattr_ret; char *tmp; int sock; krb5_flags authopts; krb5_error_code status; enum kcmd_proto kcmd_proto = KCMD_NEW_PROTOCOL; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); if (__init_suid_priv(0, PRIV_NET_PRIVADDR, NULL) == -1) { (void) fprintf(stderr, gettext("Insufficient privileges, " "rlogin must be set-uid root\n")); exit(1); } { int it; if ((getattr_ret = tcgetattr(STDIN_FILENO, &savetty)) < 0) perror("tcgetattr"); it = ioctl(STDIN_FILENO, I_FIND, "ttcompat"); if (it < 0) { perror("ioctl I_FIND ttcompat"); return (EXIT_FAILURE); } if (it == 0) { if (ioctl(STDIN_FILENO, I_PUSH, "ttcompat") < 0) { perror("ioctl I_PUSH ttcompat"); exit(EXIT_FAILURE); } ttcompat = B_TRUE; } } /* * Determine command name used to invoke to rlogin(1). Users can * create links named by a host pointing to the binary and type * "hostname" to log into that host afterwards. */ cmd = strrchr(argv[0], '/'); cmd = (cmd != NULL) ? (cmd + 1) : argv[0]; if (strcmp(cmd, rlogin) == 0) { if (argc < 2) usage(); if (*argv[1] != '-') { host = argv[1]; argc--; argv[1] = argv[0]; argv++; } } else { host = cmd; } while ((c = getopt(argc, argv, DEBUGOPTSTRING "8AEFLP:ade:fk:l:x")) != -1) { switch (c) { case '8': eight = B_TRUE; break; case 'A': krb5auth_flag = B_TRUE; break; #ifdef DEBUG case 'D': portnumber = htons(atoi(optarg)); krb5auth_flag = B_TRUE; break; #endif /* DEBUG */ case 'E': nocmdchar = B_TRUE; break; case 'F': if (fflag) usage_forward(); Fflag = 1; krb5auth_flag = B_TRUE; fwdable_done = B_TRUE; break; case 'f': if (Fflag) usage_forward(); fflag = 1; krb5auth_flag = B_TRUE; fwd_done = B_TRUE; break; case 'L': litout = B_TRUE; break; case 'P': if (strcmp(optarg, "N") == 0) kcmd_proto = KCMD_NEW_PROTOCOL; else if (strcmp(optarg, "O") == 0) kcmd_proto = KCMD_OLD_PROTOCOL; else die(gettext("rlogin: Only -PN or -PO " "allowed.\n")); if (rcmdoption_done) die(gettext("rlogin: Only one of -PN and -PO " "allowed.\n")); rcmdoption_done = B_TRUE; krb5auth_flag = B_TRUE; break; case 'a': /* * Force the remote host to prompt for a password by sending * a NULL username. This option is mutually exclusive with * the -A, -x, -f, -F, -k <realm> options. */ null_local_username = B_TRUE; break; case 'd': options |= SO_DEBUG; break; case 'e': { int c; cp = optarg; if ((c = *cp) != '\\') { cmdchar = c; } else { c = cp[1]; if (c == '\0' || c == '\\') { cmdchar = '\\'; } else if (c >= '0' && c <= '7') { long lc; lc = strtol(&cp[1], NULL, 8); if (lc < 0 || lc > 255) die(gettext("rlogin: octal " "escape character %s too " "large.\n"), cp); cmdchar = (char)lc; } else { die(gettext("rlogin: unrecognized " "escape character option %s.\n"), cp); } } break; } case 'k': krb_realm = optarg; krb5auth_flag = B_TRUE; break; case 'l': name = optarg; break; case 'x': encrypt_flag = 1; krb5auth_flag = B_TRUE; encrypt_done = B_TRUE; break; default: usage(); } } argc -= optind; argv += optind; if (host == NULL) { if (argc == 0) usage(); argc--; host = *argv++; } if (argc > 0) usage(); pwd = getpwuid(uid = getuid()); if (pwd == NULL) { (void) fprintf(stderr, gettext("getpwuid(): can not find " "password entry for user id %d."), uid); return (EXIT_FAILURE); } if (name == NULL) name = pwd->pw_name; /* * If the `-a' option is issued on the cmd line, we reset all * flags associated with other KRB5 specific options, since * the -a option is mutually exclusive with the rest. */ if (null_local_username) { krb5auth_flag = B_FALSE; fflag = Fflag = encrypt_flag = 0; (void) fprintf(stderr, gettext("Note: The -a option nullifies " "all other Kerberos-specific\noptions " "you may have used.\n")); } if (krb5auth_flag) { status = krb5_init_context(&bsd_context); if (status) { com_err(rlogin, status, gettext("while initializing" " krb5")); return (EXIT_FAILURE); } /* * Set up buffers for desread and deswrite. */ desinbuf.data = des_inbuf; desoutbuf.data = des_outbuf; desinbuf.length = sizeof (des_inbuf); desoutbuf.length = sizeof (des_outbuf); /* * Get our local realm to look up local realm options. */ status = krb5_get_default_realm(bsd_context, &realmdef[1]); if (status) { com_err(rlogin, status, gettext("while getting default realm")); return (EXIT_FAILURE); } /* * Check the realms section in krb5.conf for encryption, * forward & forwardable info */ profile_get_options_boolean(bsd_context->profile, realmdef, option); /* * Check the appdefaults section */ profile_get_options_boolean(bsd_context->profile, appdef, option); profile_get_options_string(bsd_context->profile, appdef, rcmdversion); /* * Set the *_flag variables, if the corresponding *_done are * set to 1, because we dont want the config file values * overriding the command line options. */ if (encrypt_done) encrypt_flag = 1; if (fwd_done) { fflag = 1; Fflag = 0; } else if (fwdable_done) { Fflag = 1; fflag = 0; } if (!rcmdoption_done && (rcmdproto != NULL)) { if (strncmp(rcmdproto, "rcmdv2", 6) == 0) { kcmd_proto = KCMD_NEW_PROTOCOL; } else if (strncmp(rcmdproto, "rcmdv1", 6) == 0) { kcmd_proto = KCMD_OLD_PROTOCOL; } else { (void) fprintf(stderr, gettext("Unrecognized " "KCMD protocol (%s)"), rcmdproto); return (EXIT_FAILURE); } } if (encrypt_flag && (!krb5_privacy_allowed())) { (void) fprintf(stderr, gettext("rlogin: "******"Encryption not supported.\n")); return (EXIT_FAILURE); } } if (port_number == 0) { if (krb5auth_flag) { struct servent *sp; /* * If the krb5auth_flag is set (via -A, -f, -F, -k) & * if there is an entry in /etc/services for Kerberos * login, attempt to login with Kerberos. If we fail * at any step, use the standard rlogin */ sp = getservbyname(encrypt_flag ? "eklogin" : "klogin", "tcp"); if (sp == NULL) { port_number = encrypt_flag ? htons(2105) : htons(543); } else { port_number = sp->s_port; } } else { port_number = htons(IPPORT_LOGINSERVER); } } cp = getenv("TERM"); if (cp) { (void) strncpy(term, cp, sizeof (term)); term[sizeof (term) - 1] = '\0'; } if (getattr_ret == 0) { speed = cfgetospeed(&savetty); /* * "Be conservative in what we send" -- Only send baud rates * which at least all 4.x BSD derivatives are known to handle * correctly. * NOTE: This code assumes new termios speed values will * be "higher" speeds. */ if (speed > B38400) speed = B38400; } /* * Only put the terminal speed info in if we have room * so we don't overflow the buffer, and only if we have * a speed we recognize. */ if (speed > 0 && speed < sizeof (speeds)/sizeof (char *) && strlen(term) + strlen("/") + strlen(speeds[speed]) + 1 < sizeof (term)) { (void) strcat(term, "/"); (void) strcat(term, speeds[speed]); } (void) sigset(SIGPIPE, (sigdisp_t)lostpeer); /* will use SIGUSR1 for window size hack, so hold it off */ oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); /* * Determine if v4 literal address and if so store it to one * side. This is to correct the undesired behaviour of rcmd_af * which converts a passed in v4 literal address to a v4 mapped * v6 literal address. If it was a v4 literal we then re-assign * it to host. */ tmp = NULL; if (inet_addr(host) != (in_addr_t)-1) tmp = host; if (krb5auth_flag) { authopts = AP_OPTS_MUTUAL_REQUIRED; /* Piggy-back forwarding flags on top of authopts; */ /* they will be reset in kcmd */ if (fflag || Fflag) authopts |= OPTS_FORWARD_CREDS; if (Fflag) authopts |= OPTS_FORWARDABLE_CREDS; status = kcmd(&sock, &host, port_number, null_local_username ? "" : pwd->pw_name, name, term, NULL, "host", krb_realm, bsd_context, &auth_context, &cred, NULL, /* No need for sequence number */ NULL, /* No need for server seq # */ authopts, 0, /* Not any port # */ &kcmd_proto); if (status != 0) { /* * If new protocol requested, we dont fallback to * less secure ones. */ if (kcmd_proto == KCMD_NEW_PROTOCOL) { (void) fprintf(stderr, gettext("rlogin: kcmdv2 " "to host %s failed - %s\n" "Fallback to normal rlogin denied."), host, error_message(status)); return (EXIT_FAILURE); } if (status != -1) { (void) fprintf(stderr, gettext("rlogin: kcmd " "to host %s failed - %s,\n" "trying normal rlogin...\n\n"), host, error_message(status)); } else { (void) fprintf(stderr, gettext("trying normal rlogin...\n")); } /* * kcmd() failed, so we have to * fallback to normal rlogin */ port_number = htons(IPPORT_LOGINSERVER); krb5auth_flag = B_FALSE; fflag = Fflag = encrypt_flag = 0; null_local_username = B_FALSE; } else { (void) fprintf(stderr, gettext("connected with Kerberos V5\n")); /* * Setup eblock for desread and deswrite. */ session_key = &cred->keyblock; if (kcmd_proto == KCMD_NEW_PROTOCOL) { status = krb5_auth_con_getlocalsubkey( bsd_context, auth_context, &session_key); if (status) { com_err(rlogin, status, "determining subkey for session"); return (EXIT_FAILURE); } if (session_key == NULL) { com_err(rlogin, 0, "no subkey negotiated for " "connection"); return (EXIT_FAILURE); } } eblock.crypto_entry = session_key->enctype; eblock.key = (krb5_keyblock *)session_key; init_encrypt(encrypt_flag, bsd_context, kcmd_proto, &desinbuf, &desoutbuf, CLIENT, &eblock); rem = sock; if (rem < 0) pop(EXIT_FAILURE); } } /* * Don't merge this with the "if" statement above because * "krb5auth_flag" might be set to false inside it. */ if (!krb5auth_flag) { rem = rcmd_af(&host, port_number, null_local_username ? "" : pwd->pw_name, name, term, NULL, AF_INET6); if (rem < 0) pop(EXIT_FAILURE); } /* Never need our privilege again */ __priv_relinquish(); if (tmp != NULL) host = tmp; if (options & SO_DEBUG && setsockopt(rem, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) perror("rlogin: setsockopt (SO_DEBUG)"); { int bufsize = 8192; (void) setsockopt(rem, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof (int)); } doit(oldmask); return (0); }
/* VARARGS */ int main(int argc, char **argv) { int c, rem; char *cmd, *cp, **ap, buf[RSH_BUFSIZ], **argv0, *args, *args_no_x; char *host = NULL, *user = NULL; int cc; boolean_t asrsh = B_FALSE; struct passwd *pwd; boolean_t readfrom_rem; boolean_t readfrom_rfd2; int one = 1; int omask; boolean_t nflag = B_FALSE; char *krb_realm = NULL; krb5_flags authopts; krb5_error_code status; enum kcmd_proto kcmd_proto = KCMD_NEW_PROTOCOL; uid_t uid = getuid(); c = (argc + 1) * sizeof (char *); if ((argv0 = malloc(c)) == NULL) { perror("malloc"); return (EXIT_FAILURE); } (void) memcpy(argv0, argv, c); (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); /* * Determine command name used to invoke to rlogin(1). Users can * create links named by a host pointing to the binary and type * "hostname" to log into that host afterwards. */ cmd = strrchr(argv[0], '/'); cmd = (cmd != NULL) ? (cmd + 1) : argv[0]; /* * Add "remsh" as an alias for "rsh" (System III, V networking * add-ons often used this name for the remote shell since rsh * was already taken for the restricted shell). Note that this * usurps the ability to use "remsh" as the name of a host (by * symlinking it to rsh), so we go one step farther: if the * file "/usr/bin/remsh" does not exist, we behave as if "remsh" * is a host name. If it does exist, we accept "remsh" as an * "rsh" alias. */ if (strcmp(cmd, "remsh") == 0) { struct stat sb; if (stat("/usr/bin/remsh", &sb) < 0) host = cmd; } else if (strcmp(cmd, "rsh") != 0) { host = cmd; } /* Handle legacy synopsis "rsh hostname options [command]". */ if (host == NULL) { if (argc < 2) usage(); if (*argv[1] != '-') { host = argv[1]; argc--; argv[1] = argv[0]; argv++; asrsh = B_TRUE; } } while ((c = getopt(argc, argv, DEBUGOPTSTRING "8AFKLP:ade:fk:l:nwx")) != -1) { switch (c) { #ifdef DEBUG case 'D': portnumber = htons(atoi(optarg)); krb5auth_flag++; break; #endif /* DEBUG */ case 'F': if (fflag) usage_forward(); Fflag = 1; krb5auth_flag++; fwdable_done = B_TRUE; break; case 'f': if (Fflag) usage_forward(); fflag = 1; krb5auth_flag++; fwd_done = B_TRUE; break; case 'P': if (strcmp(optarg, "N") == 0) kcmd_proto = KCMD_NEW_PROTOCOL; else if (strcmp(optarg, "O") == 0) kcmd_proto = KCMD_OLD_PROTOCOL; else die(gettext("rsh: Only -PN or -PO " "allowed.\n")); if (rcmdoption_done) die(gettext("rsh: Only one of -PN and -PO " "allowed.\n")); rcmdoption_done = B_TRUE; krb5auth_flag++; break; case 'a': krb5auth_flag++; break; case 'K': no_krb5auth_flag++; break; case 'd': options |= SO_DEBUG; break; case 'k': krb_realm = optarg; krb5auth_flag++; break; case 'l': user = optarg; break; case 'n': if (!nflag) { if (close(STDIN_FILENO) < 0) { perror("close"); return (EXIT_FAILURE); } /* * "STDION_FILENO" defined to 0 by POSIX * and hence the lowest file descriptor. * So the open(2) below is guaranteed to * reopen it because we closed it above. */ if (open("/dev/null", O_RDONLY) < 0) { perror("open"); return (EXIT_FAILURE); } nflag = B_TRUE; } break; case 'x': encrypt_flag = 1; krb5auth_flag++; encrypt_done = B_TRUE; break; /* * Ignore the -L, -w, -e and -8 flags to allow aliases with * rlogin to work. Actually rlogin(1) doesn't understand * -w either but because "rsh -w hostname command" used * to work we still accept it. */ case '8': case 'L': case 'e': case 'w': /* * On the lines of the -L, -w, -e and -8 options above, we * ignore the -A option too, in order to allow aliases with * rlogin to work. * * Mind you !, the -a option to trigger Kerberos authentication * in rsh, has a totally different usage in rlogin, its the * -A option (in rlogin) which needs to be used to talk * Kerberos. */ case 'A': break; default: usage(); } } argc -= optind; argv += optind; if (host == NULL) { if (argc == 0) usage(); argc--; host = *argv++; asrsh = B_TRUE; } if (argc == 0) { (void) setreuid(uid, uid); if (nflag) usage(); if (asrsh) *argv0 = "rlogin"; (void) execv(rlogin_path, argv0); perror(rlogin_path); (void) fprintf(stderr, gettext("No local rlogin " "program found.\n")); return (EXIT_FAILURE); } if (__init_suid_priv(0, PRIV_NET_PRIVADDR, NULL) == -1) { (void) fprintf(stderr, gettext("Insufficient privileges, " "rsh must be set-uid root\n")); return (EXIT_FAILURE); } pwd = getpwuid(uid); if (pwd == NULL) { (void) fprintf(stderr, gettext("who are you?\n")); return (EXIT_FAILURE); } if (user == NULL) user = pwd->pw_name; /* * if the user disables krb5 on the cmdline (-K), then skip * all krb5 setup. * * if the user does not disable krb5 or enable krb5 on the * cmdline, check krb5.conf to see if it should be enabled. */ if (no_krb5auth_flag) { krb5auth_flag = 0; Fflag = fflag = encrypt_flag = 0; } else if (!krb5auth_flag) { /* is autologin set in krb5.conf? */ status = krb5_init_context(&bsd_context); /* don't sweat failure here */ if (!status) { /* * note that the call to profile_get_options_boolean * with autologin_option can affect value of * krb5auth_flag */ (void) profile_get_options_boolean(bsd_context->profile, appdef, autologin_option); } } if (krb5auth_flag) { if (!bsd_context) { status = krb5_init_context(&bsd_context); if (status) { com_err("rsh", status, "while initializing krb5"); return (EXIT_FAILURE); } } /* * Get our local realm to look up local realm options. */ status = krb5_get_default_realm(bsd_context, &realmdef[1]); if (status) { com_err("rsh", status, gettext("while getting default realm")); return (EXIT_FAILURE); } /* * Check the realms section in krb5.conf for encryption, * forward & forwardable info */ profile_get_options_boolean(bsd_context->profile, realmdef, option); /* * Check the appdefaults section */ profile_get_options_boolean(bsd_context->profile, appdef, option); profile_get_options_string(bsd_context->profile, appdef, rcmdversion); /* * Set the *_flag variables, if the corresponding *_done are * set to 1, because we dont want the config file values * overriding the command line options. */ if (encrypt_done) encrypt_flag = 1; if (fwd_done) { fflag = 1; Fflag = 0; } else if (fwdable_done) { Fflag = 1; fflag = 0; } if (!rcmdoption_done && (rcmdproto != NULL)) { if (strncmp(rcmdproto, "rcmdv2", 6) == 0) { kcmd_proto = KCMD_NEW_PROTOCOL; } else if (strncmp(rcmdproto, "rcmdv1", 6) == 0) { kcmd_proto = KCMD_OLD_PROTOCOL; } else { (void) fprintf(stderr, gettext("Unrecognized " "KCMD protocol (%s)"), rcmdproto); return (EXIT_FAILURE); } } if (encrypt_flag && (!krb5_privacy_allowed())) { (void) fprintf(stderr, gettext("rsh: Encryption not " "supported.\n")); return (EXIT_FAILURE); } } /* * Connect with the service (shell/kshell) on the daemon side */ if (portnumber == 0) { while (!init_service(krb5auth_flag)) { /* * Connecting to the 'kshell' service failed, * fallback to normal rsh; Reset all KRB5 flags * and connect to 'shell' service on the server */ krb5auth_flag = 0; encrypt_flag = fflag = Fflag = 0; } } cc = encrypt_flag ? strlen(dash_x) : 0; for (ap = argv; *ap != NULL; ap++) cc += strlen(*ap) + 1; cp = args = malloc(cc); if (cp == NULL) perror("malloc"); if (encrypt_flag) { int length; length = strlcpy(args, dash_x, cc); cp += length; cc -= length; } args_no_x = args; for (ap = argv; *ap != NULL; ap++) { int length; length = strlcpy(cp, *ap, cc); assert(length < cc); cp += length; cc -= length; if (ap[1] != NULL) { *cp++ = ' '; cc--; } } if (krb5auth_flag) { authopts = AP_OPTS_MUTUAL_REQUIRED; /* * Piggy-back forwarding flags on top of authopts; * they will be reset in kcmd */ if (fflag || Fflag) authopts |= OPTS_FORWARD_CREDS; if (Fflag) authopts |= OPTS_FORWARDABLE_CREDS; status = kcmd(&rem, &host, portnumber, pwd->pw_name, user, args, &rfd2, "host", krb_realm, bsd_context, &auth_context, &cred, NULL, /* No need for sequence number */ NULL, /* No need for server seq # */ authopts, 1, /* Always set anyport */ &kcmd_proto); if (status != 0) { /* * If new protocol requested, we dont fallback to * less secure ones. */ if (kcmd_proto == KCMD_NEW_PROTOCOL) { (void) fprintf(stderr, gettext("rsh: kcmdv2 " "to host %s failed - %s\n" "Fallback to normal rsh denied."), host, error_message(status)); return (EXIT_FAILURE); } /* check NO_TKT_FILE or equivalent... */ if (status != -1) { (void) fprintf(stderr, gettext("rsh: kcmd to host %s failed - %s\n" "trying normal rsh...\n\n"), host, error_message(status)); } else { (void) fprintf(stderr, gettext("trying normal rsh...\n")); } /* * kcmd() failed, so we now fallback to normal rsh, * after resetting the KRB5 flags and the 'args' array */ krb5auth_flag = 0; encrypt_flag = fflag = Fflag = 0; args = args_no_x; (void) init_service(B_FALSE); } else { /* * Set up buffers for desread and deswrite. */ desinbuf.data = des_inbuf; desoutbuf.data = des_outbuf; desinbuf.length = sizeof (des_inbuf); desoutbuf.length = sizeof (des_outbuf); session_key = &cred->keyblock; if (kcmd_proto == KCMD_NEW_PROTOCOL) { status = krb5_auth_con_getlocalsubkey( bsd_context, auth_context, &session_key); if (status) { com_err("rsh", status, "determining subkey for session"); return (EXIT_FAILURE); } if (session_key == NULL) { com_err("rsh", 0, "no subkey " "negotiated for connection"); return (EXIT_FAILURE); } } eblock.crypto_entry = session_key->enctype; eblock.key = (krb5_keyblock *)session_key; init_encrypt(encrypt_flag, bsd_context, kcmd_proto, &desinbuf, &desoutbuf, CLIENT, &eblock); if (encrypt_flag) { char *s = gettext("This rsh session is using " "encryption for all data transmissions."); (void) write(STDERR_FILENO, s, strlen(s)); (void) write(STDERR_FILENO, "\r\n", 2); } } } /* * Don't merge this with the "if" statement above because * "krb5auth_flag" might be set to false inside it. */ if (!krb5auth_flag) { rem = rcmd_af(&host, portnumber, pwd->pw_name, user, args, &rfd2, AF_INET6); if (rem < 0) return (EXIT_FAILURE); } __priv_relinquish(); if (rfd2 < 0) { (void) fprintf(stderr, gettext("rsh: can't establish " "stderr\n")); return (EXIT_FAILURE); } if (options & SO_DEBUG) { if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (char *)&one, sizeof (one)) < 0) perror("rsh: setsockopt (stdin)"); if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (char *)&one, sizeof (one)) < 0) perror("rsh: setsockopt (stderr)"); } omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM)); if (sigdisp(SIGINT) != SIG_IGN) (void) sigset(SIGINT, sendsig); if (sigdisp(SIGQUIT) != SIG_IGN) (void) sigset(SIGQUIT, sendsig); if (sigdisp(SIGTERM) != SIG_IGN) (void) sigset(SIGTERM, sendsig); if (nflag) { (void) shutdown(rem, SHUT_WR); } else { child_pid = fork(); if (child_pid < 0) { perror("rsh: fork"); return (EXIT_FAILURE); } if (!encrypt_flag) { (void) ioctl(rfd2, FIONBIO, &one); (void) ioctl(rem, FIONBIO, &one); } if (child_pid == 0) { /* Child */ fd_set remset; char *bp; int wc; (void) close(rfd2); reread: errno = 0; cc = read(0, buf, sizeof (buf)); if (cc <= 0) goto done; bp = buf; rewrite: FD_ZERO(&remset); FD_SET(rem, &remset); if (select(rem + 1, NULL, &remset, NULL, NULL) < 0) { if (errno != EINTR) { perror("rsh: select"); return (EXIT_FAILURE); } goto rewrite; } if (!FD_ISSET(rem, &remset)) goto rewrite; writeiv = B_FALSE; wc = desrshwrite(rem, bp, cc); if (wc < 0) { if (errno == EWOULDBLOCK) goto rewrite; goto done; } cc -= wc; bp += wc; if (cc == 0) goto reread; goto rewrite; done: (void) shutdown(rem, SHUT_WR); return (EXIT_SUCCESS); } } #define MAX(a, b) (((a) > (b)) ? (a) : (b)) sigsetmask(omask); readfrom_rem = B_TRUE; readfrom_rfd2 = B_TRUE; (void) sigset(SIGPIPE, sigpipehandler); do { fd_set readyset; FD_ZERO(&readyset); if (readfrom_rem) FD_SET(rem, &readyset); if (readfrom_rfd2) FD_SET(rfd2, &readyset); if (select(MAX(rem, rfd2) + 1, &readyset, NULL, NULL, NULL) < 0) { if (errno != EINTR) { perror("rsh: select"); return (EXIT_FAILURE); } continue; } if (FD_ISSET(rfd2, &readyset)) { errno = 0; readiv = B_TRUE; cc = desrshread(rfd2, buf, sizeof (buf)); if (cc <= 0) { if (errno != EWOULDBLOCK) readfrom_rfd2 = B_FALSE; } else { (void) write(STDERR_FILENO, buf, cc); } } if (FD_ISSET(rem, &readyset)) { errno = 0; readiv = B_FALSE; cc = desrshread(rem, buf, sizeof (buf)); if (cc <= 0) { if (errno != EWOULDBLOCK) readfrom_rem = B_FALSE; } else (void) write(STDOUT_FILENO, buf, cc); } } while (readfrom_rem || readfrom_rfd2); if (!nflag) (void) kill(child_pid, SIGKILL); return (EXIT_SUCCESS); }
int ucbmain(int argc, char **argv) { psinfo_t info; /* process information structure from /proc */ char *psargs = NULL; /* pointer to buffer for -w and -ww options */ char *svpsargs = NULL; struct psent *psent; int entsize; int nent; pid_t maxpid; struct tty *ttyp = tty; char *tmp; char *p; int c; pid_t pid; /* pid: process id */ pid_t ppid; /* ppid: parent process id */ int i, found; size_t size; DIR *dirp; struct dirent *dentp; char psname[100]; char asname[100]; int pdlen; size_t len; (void) setlocale(LC_ALL, ""); my_uid = getuid(); /* * This program needs the proc_owner privilege */ (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER, (char *)NULL); /* * calculate width of pid fields based on configured MAXPID * (must be at least 5 to retain output format compatibility) */ maxpid = (pid_t)sysconf(_SC_MAXPID); pidwidth = 1; while ((maxpid /= 10) > 0) ++pidwidth; pidwidth = pidwidth < 5 ? 5 : pidwidth; if (ioctl(1, TIOCGWINSZ, &win) == -1) twidth = 80; else twidth = (win.ws_col == 0 ? 80 : win.ws_col); /* add the '-' for BSD compatibility */ if (argc > 1) { if (argv[1][0] != '-' && !isdigit(argv[1][0])) { len = strlen(argv[1]) + 2; tmp = malloc(len); if (tmp != NULL) { (void) snprintf(tmp, len, "%s%s", "-", argv[1]); argv[1] = tmp; } } } setbuf(stdout, stdbuf); while ((c = getopt(argc, argv, "lcaengrSt:xuvwU")) != EOF) switch (c) { case 'g': gflg++; /* include process group leaders */ break; case 'c': /* display internal command name */ cflg++; break; case 'r': /* restrict output to running processes */ rflg++; break; case 'S': /* display time by process and all reaped children */ Sflg++; break; case 'x': /* process w/o controlling tty */ xflg++; break; case 'l': /* long listing */ lflg++; uflg = vflg = 0; break; case 'u': /* user-oriented output */ uflg++; lflg = vflg = 0; break; case 'U': /* update private database ups_data */ Uflg++; break; case 'w': /* increase display width */ if (twidth < 132) twidth = 132; else /* second w option */ twidth = NCARGS; break; case 'v': /* display virtual memory format */ vflg++; lflg = uflg = 0; break; case 'a': /* * display all processes except process group * leaders and processes w/o controlling tty */ aflg++; gflg++; break; case 'e': /* Display environment along with aguments. */ eflg++; break; case 'n': /* Display numerical output */ nflg++; break; case 't': /* restrict output to named terminal */ #define TSZ 30 tflg++; gflg++; xflg = 0; p1 = optarg; do { /* only loop through once (NTTYS = 2) */ parg = argbuf; if (ntty >= NTTYS-1) break; getarg(); if ((p = malloc(TSZ+1)) == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } p[0] = '\0'; size = TSZ; if (isdigit(*parg)) { (void) strcpy(p, "tty"); size -= 3; } (void) strncat(p, parg, size); ttyp->tdev = PRNODEV; if (parg && *parg == '?') xflg++; else { char nambuf[TSZ+6]; /* for /dev/+\0 */ struct stat64 s; (void) strcpy(nambuf, "/dev/"); (void) strcat(nambuf, p); if (stat64(nambuf, &s) == 0) ttyp->tdev = s.st_rdev; } ttyp++->tname = p; ntty++; } while (*p1); break; default: /* error on ? */ errflg++; break; } if (errflg) usage(); if (optind + 1 < argc) { /* more than one additional argument */ (void) fprintf(stderr, "ps: too many arguments\n"); usage(); } /* * The -U option is obsolete. Attempts to use it cause ps to exit * without printing anything. */ if (Uflg) exit(0); if (optind < argc) { /* user specified a specific proc id */ pflg++; p1 = argv[optind]; parg = argbuf; getarg(); if (!num(parg)) { (void) fprintf(stderr, "ps: %s is an invalid non-numeric argument for a process id\n", parg); usage(); } pidsave = (pid_t)atol(parg); aflg = rflg = xflg = 0; gflg++; } if (tflg) ttyp->tname = NULL; /* allocate an initial guess for the number of processes */ entsize = 1024; psent = malloc(entsize * sizeof (struct psent)); if (psent == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } nent = 0; /* no active entries yet */ if (lflg) { (void) sprintf(hdr, " F UID%*s%*s %%C PRI NI SZ RSS " "WCHAN S TT TIME COMMAND", pidwidth + 1, "PID", pidwidth + 1, "PPID"); } else if (uflg) { if (nflg) (void) sprintf(hdr, " UID%*s %%CPU %%MEM SZ RSS " "TT S START TIME COMMAND", pidwidth + 1, "PID"); else (void) sprintf(hdr, "USER %*s %%CPU %%MEM SZ RSS " "TT S START TIME COMMAND", pidwidth + 1, "PID"); } else if (vflg) { (void) sprintf(hdr, "%*s TT S TIME SIZE RSS %%CPU %%MEM " "COMMAND", pidwidth + 1, "PID"); } else (void) sprintf(hdr, "%*s TT S TIME COMMAND", pidwidth + 1, "PID"); twidth = twidth - strlen(hdr) + 6; (void) printf("%s\n", hdr); if (twidth > PRARGSZ && (psargs = malloc(twidth)) == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } svpsargs = psargs; /* * Determine which processes to print info about by searching * the /proc directory and looking at each process. */ if ((dirp = opendir(procdir)) == NULL) { (void) fprintf(stderr, "ps: cannot open PROC directory %s\n", procdir); exit(1); } (void) strcpy(psname, procdir); pdlen = strlen(psname); psname[pdlen++] = '/'; /* for each active process --- */ while (dentp = readdir(dirp)) { int psfd; /* file descriptor for /proc/nnnnn/psinfo */ int asfd; /* file descriptor for /proc/nnnnn/as */ if (dentp->d_name[0] == '.') /* skip . and .. */ continue; (void) strcpy(psname + pdlen, dentp->d_name); (void) strcpy(asname, psname); (void) strcat(psname, "/psinfo"); (void) strcat(asname, "/as"); retry: if ((psfd = open(psname, O_RDONLY)) == -1) continue; asfd = -1; if (psargs != NULL || eflg) { /* now we need the proc_owner privilege */ (void) __priv_bracket(PRIV_ON); asfd = open(asname, O_RDONLY); /* drop proc_owner privilege after open */ (void) __priv_bracket(PRIV_OFF); } /* * Get the info structure for the process */ if (read(psfd, &info, sizeof (info)) != sizeof (info)) { int saverr = errno; (void) close(psfd); if (asfd > 0) (void) close(asfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) (void) fprintf(stderr, "ps: read() on %s: %s\n", psname, err_string(saverr)); continue; } (void) close(psfd); found = 0; if (info.pr_lwp.pr_state == 0) /* can't happen? */ goto closeit; pid = info.pr_pid; ppid = info.pr_ppid; /* Display only process from command line */ if (pflg) { /* pid in arg list */ if (pidsave == pid) found++; else goto closeit; } /* * Omit "uninteresting" processes unless 'g' option. */ if ((ppid == 1) && !(gflg)) goto closeit; /* * Omit non-running processes for 'r' option */ if (rflg && !(info.pr_lwp.pr_sname == 'O' || info.pr_lwp.pr_sname == 'R')) goto closeit; if (!found && !tflg && !aflg && info.pr_euid != my_uid) goto closeit; /* * Read the args for the -w and -ww cases */ if (asfd > 0) { if ((psargs != NULL && preadargs(asfd, &info, psargs) == -1) || (eflg && preadenvs(asfd, &info, psargs) == -1)) { int saverr = errno; (void) close(asfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) (void) fprintf(stderr, "ps: read() on %s: %s\n", asname, err_string(saverr)); continue; } } else { psargs = info.pr_psargs; } if (nent >= entsize) { entsize *= 2; psent = (struct psent *)realloc((char *)psent, entsize * sizeof (struct psent)); if (psent == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } } if ((psent[nent].psinfo = malloc(sizeof (psinfo_t))) == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } *psent[nent].psinfo = info; if (psargs == NULL) psent[nent].psargs = NULL; else { if ((psent[nent].psargs = malloc(strlen(psargs)+1)) == NULL) { (void) fprintf(stderr, "ps: no memory\n"); exit(1); } (void) strcpy(psent[nent].psargs, psargs); } psent[nent].found = found; nent++; closeit: if (asfd > 0) (void) close(asfd); psargs = svpsargs; } /* revert to non-privileged user */ (void) __priv_relinquish(); (void) closedir(dirp); qsort((char *)psent, nent, sizeof (psent[0]), pscompare); for (i = 0; i < nent; i++) { struct psent *pp = &psent[i]; if (prcom(pp->found, pp->psinfo, pp->psargs)) { (void) printf("\n"); retcode = 0; } } return (retcode); }