int mkdir_main(int argc, char **argv) { mode_t mode = (mode_t)(-1); int status = EXIT_SUCCESS; int flags = 0; unsigned opt; char *smode; #if ENABLE_SELINUX security_context_t scontext; #endif #if ENABLE_FEATURE_MKDIR_LONG_OPTIONS applet_long_options = mkdir_longopts; #endif opt = getopt32(argv, "m:p" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext)); if (opt & 1) { mode = 0777; if (!bb_parse_mode(smode, &mode)) { bb_error_msg_and_die("invalid mode '%s'", smode); } } if (opt & 2) flags |= FILEUTILS_RECUR; #if ENABLE_SELINUX if (opt & 4) { selinux_or_die(); setfscreatecon_or_die(scontext); } #endif if (optind == argc) { bb_show_usage(); } argv += optind; do { if (bb_make_directory(*argv, mode, flags)) { status = EXIT_FAILURE; } } while (*++argv); return status; }
mode_t getopt_mk_fifo_nod(int argc, char **argv) { mode_t mode = 0666; char *smode = NULL; #if ENABLE_SELINUX security_context_t scontext; #endif int opt; opt = getopt32(argc, argv, "m:" USE_SELINUX("Z:"), &smode USE_SELINUX(,&scontext)); if (opt & 1) { if (bb_parse_mode(smode, &mode)) umask(0); } #if ENABLE_SELINUX if (opt & 2) { selinux_or_die(); setfscreatecon_or_die(scontext); } #endif return mode; }
int sulogin_main(int argc, char **argv) { char *cp; int timeout = 0; char *timeout_arg; const char * const *p; struct passwd *pwd; const char *shell; #if ENABLE_FEATURE_SHADOWPASSWDS /* Using _r function to avoid pulling in static buffers */ char buffer[256]; struct spwd spw; struct spwd *result; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); if (getopt32(argc, argv, "t:", &timeout_arg)) { timeout = xatoi_u(timeout_arg); } if (argv[optind]) { close(0); close(1); dup(xopen(argv[optind], O_RDWR)); close(2); dup(0); } if (!isatty(0) || !isatty(1) || !isatty(2)) { logmode = LOGMODE_SYSLOG; bb_error_msg_and_die("not a tty"); } /* Clear out anything dangerous from the environment */ for (p = forbid; *p; p++) unsetenv(*p); signal(SIGALRM, catchalarm); pwd = getpwuid(0); if (!pwd) { goto auth_error; } #if ENABLE_FEATURE_SHADOWPASSWDS if (getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result)) { goto auth_error; } pwd->pw_passwd = spw.sp_pwdp; #endif while (1) { /* cp points to a static buffer that is zeroed every time */ cp = bb_askpass(timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); if (!cp || !*cp) { bb_info_msg("Normal startup"); return 0; } if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } memset(cp, 0, strlen(cp)); signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); USE_SELINUX(renew_current_security_context()); shell = getenv("SUSHELL"); if (!shell) shell = getenv("sushell"); if (!shell) { shell = "/bin/sh"; if (pwd->pw_shell[0]) shell = pwd->pw_shell; } run_shell(shell, 1, 0, 0); /* never returns */ auth_error: bb_error_msg_and_die("no password entry for 'root'"); }
int id_main(int argc UNUSED_PARAM, char **argv) { uid_t ruid; gid_t rgid; uid_t euid; gid_t egid; unsigned opt; int i; int status = EXIT_SUCCESS; const char *prefix; const char *username; #if ENABLE_SELINUX security_context_t scontext = NULL; #endif /* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/ /* Don't allow more than one username */ opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G"); opt = getopt32(argv, "rnugG" USE_SELINUX("Z")); username = argv[optind]; if (username) { struct passwd *p = xgetpwnam(username); euid = ruid = p->pw_uid; egid = rgid = p->pw_gid; } else { egid = getegid(); rgid = getgid(); euid = geteuid(); ruid = getuid(); } /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */ /* id says: print the real ID instead of the effective ID, with -ugG */ /* in fact in this case egid is always printed if egid != rgid */ if (!opt || (opt & JUST_ALL_GROUPS)) { gid_t *groups; int n; if (!opt) { /* Default Mode */ status |= print_user(ruid, "uid="); status |= print_group(rgid, " gid="); if (euid != ruid) status |= print_user(euid, " euid="); if (egid != rgid) status |= print_group(egid, " egid="); } else { /* JUST_ALL_GROUPS */ status |= print_group(rgid, NULL); if (egid != rgid) status |= print_group(egid, " "); } /* We are supplying largish buffer, trying * to not run get_groups() twice. That might be slow * ("user database in remote SQL server" case) */ groups = xmalloc(64 * sizeof(gid_t)); n = 64; if (get_groups(username, rgid, groups, &n) < 0) { /* Need bigger buffer after all */ groups = xrealloc(groups, n * sizeof(gid_t)); get_groups(username, rgid, groups, &n); } if (n > 0) { /* Print the list */ prefix = " groups="; for (i = 0; i < n; i++) { if (opt && (groups[i] == rgid || groups[i] == egid)) continue; status |= print_group(groups[i], opt ? " " : prefix); prefix = ","; } } else if (n < 0) { /* error in get_groups() */ if (!ENABLE_DESKTOP) bb_error_msg_and_die("cannot get groups"); else return EXIT_FAILURE; } if (ENABLE_FEATURE_CLEAN_UP) free(groups); #if ENABLE_SELINUX if (is_selinux_enabled()) { if (getcon(&scontext) == 0) printf(" context=%s", scontext); } #endif } else if (opt & PRINT_REAL) { euid = ruid; egid = rgid; } if (opt & JUST_USER) status |= print_user(euid, NULL); else if (opt & JUST_GROUP) status |= print_group(egid, NULL); #if ENABLE_SELINUX else if (opt & JUST_CONTEXT) { selinux_or_die(); if (username || getcon(&scontext)) { bb_error_msg_and_die("can't get process context%s", username ? " for a different user" : ""); } fputs(scontext, stdout); } /* freecon(NULL) seems to be harmless */ if (ENABLE_FEATURE_CLEAN_UP) freecon(scontext); #endif bb_putchar('\n'); fflush_stdout_and_exit(status); }
int netstat_main(int argc, char **argv) { int opt; int new_flags=0; int showroute = 0, extended = 0; #ifdef CONFIG_FEATURE_IPV6 int inet=1; int inet6=1; #else # define inet 1 # define inet6 0 #endif while ((opt = getopt(argc, argv, "laenrtuwx" USE_SELINUX("Z"))) != -1) switch (opt) { case 'l': flags &= ~NETSTAT_CONNECTED; flags |= NETSTAT_LISTENING; break; case 'a': flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; break; case 'n': flags |= NETSTAT_NUMERIC; break; case 'r': showroute = 1; break; case 'e': extended = 1; break; case 't': new_flags |= NETSTAT_TCP; break; case 'u': new_flags |= NETSTAT_UDP; break; case 'w': new_flags |= NETSTAT_RAW; break; case 'x': new_flags |= NETSTAT_UNIX; break; #ifdef CONFIG_SELINUX case 'Z': if (!is_selinux_enabled()) bb_error_msg_and_die("SELinux is not enabled on this machine."); flags |= NETSTAT_SELINUX; break; #endif default: bb_show_usage(); } if ( showroute ) { #ifdef CONFIG_ROUTE displayroutes ( flags & NETSTAT_NUMERIC, !extended ); return 0; #else bb_error_msg_and_die( "-r (display routing table) is not compiled in." ); #endif } if (new_flags) { flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX); flags |= new_flags; } if (flags&(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) { printf("Active Internet connections "); /* xxx */ if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED)) printf("(servers and established)"); else { if (flags&NETSTAT_LISTENING) printf("(only servers)"); else printf("(w/o servers)"); } printf("\nProto Recv-Q Send-Q Local Address Foreign Address State \n"); } if (inet && flags&NETSTAT_TCP) do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one); #ifdef CONFIG_FEATURE_IPV6 if (inet6 && flags&NETSTAT_TCP) do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one); #endif if (inet && flags&NETSTAT_UDP) do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one); #ifdef CONFIG_FEATURE_IPV6 if (inet6 && flags&NETSTAT_UDP) do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one); #endif if (inet && flags&NETSTAT_RAW) do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one); #ifdef CONFIG_FEATURE_IPV6 if (inet6 && flags&NETSTAT_RAW) do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one); #endif if (flags&NETSTAT_UNIX) { printf("Active UNIX domain sockets "); if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED)) printf("(servers and established)"); else { if (flags&NETSTAT_LISTENING) printf("(only servers)"); else printf("(w/o servers)"); } printf("\nProto RefCnt Flags Type State I-Node "); if (flags & NETSTAT_SELINUX) printf("Security Context "); printf("Path\n"); do_info(_PATH_PROCNET_UNIX,"AF UNIX",unix_do_one); } return 0; }
static void unix_do_one(int nr, const char *line) { static int has = 0; char path[PATH_MAX], ss_flags[32]; char *ss_proto, *ss_state, *ss_type; int num, state, type, inode; void *d; unsigned long refcnt, proto, unix_flags; USE_SELINUX(security_context_t unixcon = NULL); if (nr == 0) { if (strstr(line, "Inode")) has |= HAS_INODE; return; } path[0] = '\0'; num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s", &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path); if (num < 6) { bb_error_msg("warning, got bogus unix line."); return; } if (!(has & HAS_INODE)) snprintf(path,sizeof(path),"%d",inode); if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))!=(NETSTAT_LISTENING|NETSTAT_CONNECTED)) { if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) { if (!(flags&NETSTAT_LISTENING)) return; } else { if (!(flags&NETSTAT_CONNECTED)) return; } } switch (proto) { case 0: ss_proto = "unix"; break; default: ss_proto = "??"; } switch (type) { case SOCK_STREAM: ss_type = "STREAM"; break; case SOCK_DGRAM: ss_type = "DGRAM"; break; case SOCK_RAW: ss_type = "RAW"; break; case SOCK_RDM: ss_type = "RDM"; break; case SOCK_SEQPACKET: ss_type = "SEQPACKET"; break; default: ss_type = "UNKNOWN"; } switch (state) { case SS_FREE: ss_state = "FREE"; break; case SS_UNCONNECTED: /* * Unconnected sockets may be listening * for something. */ if (unix_flags & SO_ACCEPTCON) { ss_state = "LISTENING"; } else { ss_state = ""; } break; case SS_CONNECTING: ss_state = "CONNECTING"; break; case SS_CONNECTED: ss_state = "CONNECTED"; break; case SS_DISCONNECTING: ss_state = "DISCONNECTING"; break; default: ss_state = "UNKNOWN"; } strcpy(ss_flags, "[ "); if (unix_flags & SO_ACCEPTCON) strcat(ss_flags, "ACC "); if (unix_flags & SO_WAITDATA) strcat(ss_flags, "W "); if (unix_flags & SO_NOSPACE) strcat(ss_flags, "N "); strcat(ss_flags, "]"); #ifdef CONFIG_SELINUX if ((flags & NETSTAT_SELINUX) && is_selinux_enabled()) { if (lgetfilecon(path, &unixcon) < 0) unixcon = NULL; } #endif printf("%-5s %-6ld %-11s %-10s %-13s ", ss_proto, refcnt, ss_flags, ss_type, ss_state); if (has & HAS_INODE) printf("%-6d ",inode); else printf("- "); #ifdef CONFIG_SELINUX if (flags & NETSTAT_SELINUX) { printf("%-32s ", unixcon ? unixcon : "-"); if (unixcon) freecon(unixcon); } #endif puts(path); }
int sulogin_main(int argc UNUSED_PARAM, char **argv) { char *cp; int timeout = 0; struct passwd *pwd; const char *shell; #if ENABLE_FEATURE_SHADOWPASSWDS /* Using _r function to avoid pulling in static buffers */ char buffer[256]; struct spwd spw; #endif logmode = LOGMODE_BOTH; openlog(applet_name, 0, LOG_AUTH); opt_complementary = "t+"; /* -t N */ getopt32(argv, "t:", &timeout); if (argv[optind]) { close(0); close(1); dup(xopen(argv[optind], O_RDWR)); close(2); dup(0); } /* Malicious use like "sulogin /dev/sda"? */ if (!isatty(0) || !isatty(1) || !isatty(2)) { logmode = LOGMODE_SYSLOG; bb_error_msg_and_die("not a tty"); } /* Clear dangerous stuff, set PATH */ sanitize_env_if_suid(); // bb_askpass() already handles this // signal(SIGALRM, catchalarm); pwd = getpwuid(0); if (!pwd) { goto auth_error; } #if ENABLE_FEATURE_SHADOWPASSWDS { /* getspnam_r may return 0 yet set result to NULL. * At least glibc 2.4 does this. Be extra paranoid here. */ struct spwd *result = NULL; int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result); if (r || !result) { goto auth_error; } pwd->pw_passwd = result->sp_pwdp; } #endif while (1) { char *encrypted; int r; /* cp points to a static buffer that is zeroed every time */ cp = bb_askpass(timeout, "Give root password for system maintenance\n" "(or type Control-D for normal startup):"); if (!cp || !*cp) { bb_info_msg("Normal startup"); return 0; } encrypted = pw_encrypt(cp, pwd->pw_passwd, 1); r = strcmp(encrypted, pwd->pw_passwd); free(encrypted); if (r == 0) { break; } bb_do_delay(FAIL_DELAY); bb_error_msg("login incorrect"); } memset(cp, 0, strlen(cp)); // signal(SIGALRM, SIG_DFL); bb_info_msg("System Maintenance Mode"); USE_SELINUX(renew_current_security_context()); shell = getenv("SUSHELL"); if (!shell) shell = getenv("sushell"); if (!shell) { shell = "/bin/sh"; if (pwd->pw_shell[0]) shell = pwd->pw_shell; } /* Exec login shell with no additional parameters. Never returns. */ run_shell(shell, 1, NULL, NULL); auth_error: bb_error_msg_and_die("no password entry for root"); }