httpd: add -u user[:grp] support
No binary (build failed)
—
(log yok)
| @@ -29,11 +29,11 @@ | |
| static short printf_full(unsigned int id, const char *arg, const char prefix) | |
| { | |
| const char *fmt = "%cid=%u"; | |
| - | short status=EXIT_FAILURE; |
| + | short status = EXIT_FAILURE; |
| - | if(arg) { |
| + | if (arg) { |
| fmt = "%cid=%u(%s)"; | |
| - | status=EXIT_SUCCESS; |
| + | status = EXIT_SUCCESS; |
| } | |
| bb_printf(fmt, prefix, id, arg); | |
| return status; | |
| @@ -60,21 +60,21 @@ int id_main(int argc, char **argv) | |
| gid = getgid(); | |
| } | |
| - | if(argv[optind]) { |
| - | p=getpwnam(argv[optind]); |
| + | if (argv[optind]) { |
| + | p = getpwnam(argv[optind]); |
| /* bb_xgetpwnam is needed because it exits on failure */ | |
| uid = bb_xgetpwnam(argv[optind]); | |
| gid = p->pw_gid; | |
| /* in this case PRINT_REAL is the same */ | |
| } | |
| - | if(flags & (JUST_GROUP | JUST_USER)) { |
| + | if (flags & (JUST_GROUP | JUST_USER)) { |
| /* JUST_GROUP and JUST_USER are mutually exclusive */ | |
| - | if(flags & NAME_NOT_NUMBER) { |
| + | if (flags & NAME_NOT_NUMBER) { |
| /* bb_getpwuid and bb_getgrgid exit on failure so puts cannot segfault */ | |
| puts((flags & JUST_USER) ? bb_getpwuid(NULL, uid, -1 ) : bb_getgrgid(NULL, gid, -1 )); | |
| } else { | |
| - | bb_printf("%u\n",(flags & JUST_USER) ? uid : gid); |
| + | bb_printf("%u\n", (flags & JUST_USER) ? uid : gid); |
| } | |
| /* exit */ | |
| bb_fflush_stdout_and_exit(EXIT_SUCCESS); | |
| @@ -82,13 +82,13 @@ int id_main(int argc, char **argv) | |
| /* Print full info like GNU id */ | |
| /* bb_getpwuid doesn't exit on failure here */ | |
| - | status=printf_full(uid, bb_getpwuid(NULL, uid, 0), 'u'); |
| + | status = printf_full(uid, bb_getpwuid(NULL, uid, 0), 'u'); |
| putchar(' '); | |
| /* bb_getgrgid doesn't exit on failure here */ | |
| - | status|=printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g'); |
| + | status |= printf_full(gid, bb_getgrgid(NULL, gid, 0), 'g'); |
| #ifdef CONFIG_SELINUX | |
| - | if ( is_selinux_enabled() ) { |
| + | if (is_selinux_enabled()) { |
| security_context_t mysid; | |
| char context[80]; | |
| int len = sizeof(context); | |
| @@ -99,8 +99,8 @@ int id_main(int argc, char **argv) | |
| len = strlen(mysid)+1; | |
| safe_strncpy(context, mysid, len); | |
| freecon(mysid); | |
| - | }else{ |
| - | safe_strncpy(context, "unknown",8); |
| + | } else { |
| + | safe_strncpy(context, "unknown", 8); |
| } | |
| bb_printf(" context=%s", context); | |
| } | |
| @@ -20,8 +20,6 @@ | |
| #include "ext2_fs.h" | |
| #include "ext2fs.h" | |
| - | //#include "../../version.h" |
| - | |
| static const char *lib_version = E2FSPROGS_VERSION; | |
| static const char *lib_date = E2FSPROGS_DATE; | |
| @@ -291,6 +291,13 @@ extern char *bb_getug(char *buffer, char *idname, long id, int bufsize, char pre | |
| extern char *bb_getpwuid(char *name, long uid, int bufsize); | |
| extern char *bb_getgrgid(char *group, long gid, int bufsize); | |
| extern char *bb_askpass(int timeout, const char * prompt); | |
| + | /* from chpst */ |
| + | struct bb_uidgid_t { |
| + | uid_t uid; |
| + | gid_t gid; |
| + | }; |
| + | extern unsigned uidgid_get(struct bb_uidgid_t*, const char* /*, unsigned*/); |
| + | |
| extern int device_open(const char *device, int mode); | |
| @@ -1167,7 +1167,7 @@ USE_FEATURE_DATE_ISOFMT( \ | |
| #define httpd_trivial_usage \ | |
| "[-c <conf file>]" \ | |
| USE_FEATURE_HTTPD_WITHOUT_INETD(" [-p <port>]") \ | |
| - | USE_FEATURE_HTTPD_SETUID(" [-u user]") \ |
| + | USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \ |
| USE_FEATURE_HTTPD_BASIC_AUTH(" [-r <realm>]") \ | |
| USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \ | |
| " [-h home]" \ | |
| @@ -1176,12 +1176,12 @@ USE_FEATURE_DATE_ISOFMT( \ | |
| "Listens for incoming http server requests.\n\n" \ | |
| "Options:\n" \ | |
| "\t-c FILE\t\tSpecifies configuration file. (default httpd.conf)\n" \ | |
| - | USE_FEATURE_HTTPD_WITHOUT_INETD("\t-p PORT\tServer port (default 80)\n") \ |
| - | USE_FEATURE_HTTPD_SETUID("\t-u USER\tSet uid to USER after listening privileges port\n") \ |
| + | USE_FEATURE_HTTPD_WITHOUT_INETD("\t-p PORT\t\tServer port (default 80)\n") \ |
| + | USE_FEATURE_HTTPD_SETUID("\t-u USER[:GRP]\tSet uid/gid after binding to port\n") \ |
| USE_FEATURE_HTTPD_BASIC_AUTH("\t-r REALM\tAuthentication Realm for Basic Authentication\n") \ | |
| USE_FEATURE_HTTPD_AUTH_MD5("\t-m PASS\t\tCrypt PASS with md5 algorithm\n") \ | |
| - | "\t-h HOME \tSpecifies http HOME directory (default ./)\n" \ |
| - | "\t-e STRING\tHtml encode STRING\n" \ |
| + | "\t-h HOME\t\tSpecifies http HOME directory (default ./)\n" \ |
| + | "\t-e STRING\tHTML encode STRING\n" \ |
| "\t-d STRING\tURL decode STRING" | |
| #define hwclock_trivial_usage \ | |
| @@ -15,6 +15,7 @@ | |
| /* Like strncpy but make sure the resulting string is always 0 terminated. */ | |
| char * safe_strncpy(char *dst, const char *src, size_t size) | |
| { | |
| - | dst[size-1] = '\0'; |
| - | return strncpy(dst, src, size-1); |
| + | if (!size) return dst; |
| + | dst[--size] = '\0'; |
| + | return strncpy(dst, src, size); |
| } | |
| @@ -4,4 +4,4 @@ | |
| # | |
| # Licensed under the GPL v2, see the file LICENSE in this tarball. | |
| - | lib-y:=pwd_grp.o |
| + | lib-y:=pwd_grp.o uidgid_get.o |
| @@ -0,0 +1,49 @@ | |
| + | #include "busybox.h" |
| + | |
| + | unsigned uidgid_get(struct bb_uidgid_t *u, const char *ug /*, unsigned dogrp */) |
| + | { |
| + | struct passwd *pwd; |
| + | struct group *gr; |
| + | const char *g; |
| + | |
| + | /* g = 0; if (dogrp) g = strchr(ug, ':'); */ |
| + | g = strchr(ug, ':'); |
| + | if (g) { |
| + | int sz = (++g) - ug; |
| + | char buf[sz]; |
| + | safe_strncpy(buf, ug, sz); |
| + | pwd = getpwnam(buf); |
| + | } else |
| + | pwd = getpwnam(ug); |
| + | if (!pwd) |
| + | return 0; |
| + | u->uid = pwd->pw_uid; |
| + | u->gid = pwd->pw_gid; |
| + | if (g) { |
| + | gr = getgrnam(g); |
| + | if (!gr) return 0; |
| + | u->gid = gr->gr_gid; |
| + | } |
| + | return 1; |
| + | } |
| + | |
| + | #if 0 |
| + | #include <stdio.h> |
| + | int main() |
| + | { |
| + | unsigned u; |
| + | struct bb_uidgid_t ug; |
| + | u = uidgid_get(&ug, "apache"); |
| + | printf("%u = %u:%u\n", u, ug.uid, ug.gid); |
| + | ug.uid = ug.gid = 1111; |
| + | u = uidgid_get(&ug, "apache"); |
| + | printf("%u = %u:%u\n", u, ug.uid, ug.gid); |
| + | ug.uid = ug.gid = 1111; |
| + | u = uidgid_get(&ug, "apache:users"); |
| + | printf("%u = %u:%u\n", u, ug.uid, ug.gid); |
| + | ug.uid = ug.gid = 1111; |
| + | u = uidgid_get(&ug, "apache:users"); |
| + | printf("%u = %u:%u\n", u, ug.uid, ug.gid); |
| + | return 0; |
| + | } |
| + | #endif |
| @@ -1916,8 +1916,8 @@ int httpd_main(int argc, char *argv[]) | |
| USE_FEATURE_HTTPD_WITHOUT_INETD(const char *s_port;) | |
| USE_FEATURE_HTTPD_WITHOUT_INETD(int server;) | |
| - | USE_FEATURE_HTTPD_SETUID(const char *s_uid;) |
| - | USE_FEATURE_HTTPD_SETUID(long uid = -1;) |
| + | USE_FEATURE_HTTPD_SETUID(const char *s_ugid = NULL;) |
| + | USE_FEATURE_HTTPD_SETUID(struct bb_uidgid_t ugid;) |
| USE_FEATURE_HTTPD_AUTH_MD5(const char *pass;) | |
| @@ -1937,7 +1937,7 @@ int httpd_main(int argc, char *argv[]) | |
| USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) | |
| USE_FEATURE_HTTPD_BASIC_AUTH(, &(config->realm)) | |
| USE_FEATURE_HTTPD_AUTH_MD5(, &pass) | |
| - | USE_FEATURE_HTTPD_SETUID(, &s_uid) |
| + | USE_FEATURE_HTTPD_SETUID(, &s_ugid) |
| USE_FEATURE_HTTPD_WITHOUT_INETD(, &s_port) | |
| ); | |
| @@ -1963,11 +1963,18 @@ int httpd_main(int argc, char *argv[]) | |
| #if ENABLE_FEATURE_HTTPD_SETUID | |
| if (opt & OPT_SETUID) { | |
| char *e; | |
| - | |
| - | uid = strtol(s_uid, &e, 0); |
| + | // FIXME: what the default group should be? |
| + | ugid.gid = -1; |
| + | ugid.uid = strtoul(s_ugid, &e, 0); |
| + | if (*e == ':') { |
| + | e++; |
| + | ugid.gid = strtoul(e, &e, 0); |
| + | } |
| if (*e != '\0') { | |
| /* not integer */ | |
| - | uid = bb_xgetpwnam(s_uid); |
| + | if (!uidgid_get(&ugid, s_ugid)) |
| + | bb_error_msg_and_die("unrecognized user[:group] " |
| + | "name '%s'", s_ugid); |
| } | |
| } | |
| #endif | |
| @@ -1978,8 +1985,15 @@ int httpd_main(int argc, char *argv[]) | |
| server = openServer(); | |
| # ifdef CONFIG_FEATURE_HTTPD_SETUID | |
| /* drop privileges */ | |
| - | if (uid > 0) |
| - | xsetuid(uid); |
| + | if (opt & OPT_SETUID) { |
| + | if (ugid.gid != (gid_t)-1) { |
| + | // FIXME: needed? |
| + | //if (setgroups(1, &ugid.gid) == -1) |
| + | // bb_perror_msg_and_die("setgroups"); |
| + | xsetgid(ugid.gid); |
| + | } |
| + | xsetuid(ugid.uid); |
| + | } |
| # endif | |
| #endif | |
| @@ -5,4 +5,4 @@ | |
| # Licensed under the GPL v2, see the file LICENSE in this tarball. | |
| lib-y:= | |
| - | lib-$(CONFIG_CHPST) += chpst.o uidgid.o |
| + | lib-$(CONFIG_CHPST) += chpst.o |
| @@ -1,16 +1,9 @@ | |
| #include "busybox.h" | |
| - | #include <sys/types.h> |
| - | #include <sys/resource.h> |
| - | #include <grp.h> |
| - | |
| - | #include "uidgid.h" |
| - | |
| - | #include <sys/types.h> |
| #include <dirent.h> | |
| static unsigned option_mask; | |
| - | // Must meatch constants in chpst_main! |
| + | // Must match constants in chpst_main! |
| #define OPT_verbose (option_mask & 0x2000) | |
| #define OPT_pgrp (option_mask & 0x4000) | |
| #define OPT_nostdin (option_mask & 0x8000) | |
| @@ -33,34 +26,27 @@ static long limitt = -2; | |
| static long nicelvl; | |
| static const char *root; | |
| - | static void suidgid(char *user, unsigned dogrp) |
| + | static void suidgid(char *user) |
| { | |
| - | struct uidgid ugid; |
| + | struct bb_uidgid_t ugid; |
| - | if (!uidgid_get(&ugid, user, dogrp)) { |
| - | if (dogrp) |
| - | bb_error_msg_and_die("unknown user/group: %s", user); |
| - | else |
| - | bb_error_msg_and_die("unknown account: %s", user); |
| + | if (!uidgid_get(&ugid, user)) { |
| + | bb_error_msg_and_die("unknown user/group: %s", user); |
| } | |
| - | if (setgroups(ugid.gids, ugid.gid) == -1) |
| + | if (setgroups(1, &ugid.gid) == -1) |
| bb_perror_msg_and_die("setgroups"); | |
| - | xsetgid(*ugid.gid); |
| + | xsetgid(ugid.gid); |
| xsetuid(ugid.uid); | |
| } | |
| - | static void euidgid(char *user, unsigned dogrp) |
| + | static void euidgid(char *user) |
| { | |
| - | struct uidgid ugid; |
| + | struct bb_uidgid_t ugid; |
| - | if (!uidgid_get(&ugid, user, dogrp)) { |
| - | if (dogrp) |
| - | bb_error_msg_and_die("unknown user/group: %s", user); |
| - | else |
| - | bb_error_msg_and_die("unknown account: %s", user); |
| + | if (!uidgid_get(&ugid, user)) { |
| + | bb_error_msg_and_die("unknown user/group: %s", user); |
| } | |
| - | //FIXME: ultoa needed here! |
| - | xsetenv("GID", utoa(*ugid.gid)); |
| + | xsetenv("GID", utoa(ugid.gid)); |
| xsetenv("UID", utoa(ugid.uid)); | |
| } | |
| @@ -276,8 +262,8 @@ int chpst_main(int argc, char **argv) | |
| if (nice(nicelvl) == -1) | |
| bb_perror_msg_and_die("nice"); | |
| } | |
| - | if (env_user) euidgid(env_user, 1); |
| - | if (set_user) suidgid(set_user, 1); |
| + | if (env_user) euidgid(env_user); |
| + | if (set_user) suidgid(set_user); |
| if (OPT_nostdin) close(0); | |
| if (OPT_nostdout) close(1); | |
| if (OPT_nostderr) close(2); | |
| @@ -292,7 +278,7 @@ static void setuidgid(int argc, char **argv) | |
| account = *++argv; | |
| if (!account) bb_show_usage(); | |
| if (!*++argv) bb_show_usage(); | |
| - | suidgid((char*)account, 0); |
| + | suidgid((char*)account); |
| execvp(argv[0], argv); | |
| bb_perror_msg_and_die("exec %s", argv[0]); | |
| } | |
| @@ -304,7 +290,7 @@ static void envuidgid(int argc, char **argv) | |
| account = *++argv; | |
| if (!account) bb_show_usage(); | |
| if (!*++argv) bb_show_usage(); | |
| - | euidgid((char*)account, 0); |
| + | euidgid((char*)account); |
| execvp(argv[0], argv); | |
| bb_perror_msg_and_die("exec %s", argv[0]); | |
| } | |
| @@ -1,63 +0,0 @@ | |
| - | #include <sys/types.h> |
| - | #include <pwd.h> |
| - | #include <grp.h> |
| - | #include "uidgid.h" |
| - | |
| - | static unsigned str_chr(const char *s, int c) |
| - | { |
| - | const char *t = s; |
| - | while (t[0] && t[0] != (char)c) |
| - | t++; |
| - | return t - s; |
| - | } |
| - | |
| - | |
| - | unsigned uidgid_get(struct uidgid *u, char *ug, unsigned dogrp) { |
| - | char *g = 0; |
| - | struct passwd *pwd = 0; |
| - | struct group *gr = 0; |
| - | int i, d = 0; |
| - | |
| - | if (dogrp) |
| - | d = str_chr(ug, ':'); |
| - | if (ug[d] == ':') { |
| - | ug[d] = 0; |
| - | g = ug + d + 1; |
| - | } |
| - | pwd = getpwnam(ug); |
| - | if (!pwd) { |
| - | if (g) ug[d] = ':'; |
| - | return 0; |
| - | } |
| - | if (g) { |
| - | ug[d] = ':'; |
| - | for (i = 0; i < 60; ++i) { |
| - | d = str_chr(g, ':'); |
| - | if (g[d] == ':') { |
| - | g[d] = 0; |
| - | gr = getgrnam(g); |
| - | if (!gr) { |
| - | g[d] = ':'; |
| - | return 0; |
| - | } |
| - | g[d] = ':'; |
| - | u->gid[i] = gr->gr_gid; |
| - | g += d+1; |
| - | } |
| - | else { |
| - | gr = getgrnam(g); |
| - | if (!gr) return 0; |
| - | u->gid[i++] = gr->gr_gid; |
| - | break; |
| - | } |
| - | } |
| - | u->gid[i] = 0; |
| - | u->gids = i; |
| - | } |
| - | if (!g) { |
| - | u->gid[0] = pwd->pw_gid; |
| - | u->gids = 1; |
| - | } |
| - | u->uid = pwd->pw_uid; |
| - | return 1; |
| - | } |
| @@ -1,14 +0,0 @@ | |
| - | #ifndef UIDGID_H |
| - | #define UIDGID_H |
| - | |
| - | #include <sys/types.h> |
| - | |
| - | struct uidgid { |
| - | uid_t uid; |
| - | gid_t gid[61]; |
| - | int gids; |
| - | }; |
| - | |
| - | extern unsigned uidgid_get(struct uidgid *, char *, unsigned); |
| - | |
| - | #endif |