From de59c0f58fa5dc75b753f94da61be92bfa0935ec Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 5 Oct 2006 22:50:22 +0000 Subject: [PATCH] httpd: add -u user[:grp] support --- coreutils/id.c | 26 ++++++++-------- e2fsprogs/ext2fs/version.c | 2 -- include/libbb.h | 7 +++++ include/usage.h | 10 +++--- libbb/safe_strncpy.c | 5 +-- libpwdgrp/Kbuild | 2 +- libpwdgrp/uidgid_get.c | 49 +++++++++++++++++++++++++++++ networking/httpd.c | 30 +++++++++++++----- runit/Kbuild | 2 +- runit/chpst.c | 46 ++++++++++------------------ runit/uidgid.c | 63 -------------------------------------- runit/uidgid.h | 14 --------- 12 files changed, 117 insertions(+), 139 deletions(-) create mode 100644 libpwdgrp/uidgid_get.c delete mode 100644 runit/uidgid.c delete mode 100644 runit/uidgid.h diff --git a/coreutils/id.c b/coreutils/id.c index 9e49999cd..9d605325c 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -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); } diff --git a/e2fsprogs/ext2fs/version.c b/e2fsprogs/ext2fs/version.c index 882e121d4..d2981e867 100644 --- a/e2fsprogs/ext2fs/version.c +++ b/e2fsprogs/ext2fs/version.c @@ -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; diff --git a/include/libbb.h b/include/libbb.h index ed1d780fd..adfeca590 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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); diff --git a/include/usage.h b/include/usage.h index 34b0566cd..c9e501903 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1167,7 +1167,7 @@ USE_FEATURE_DATE_ISOFMT( \ #define httpd_trivial_usage \ "[-c ]" \ USE_FEATURE_HTTPD_WITHOUT_INETD(" [-p ]") \ - USE_FEATURE_HTTPD_SETUID(" [-u user]") \ + USE_FEATURE_HTTPD_SETUID(" [-u user[:grp]]") \ USE_FEATURE_HTTPD_BASIC_AUTH(" [-r ]") \ 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 \ diff --git a/libbb/safe_strncpy.c b/libbb/safe_strncpy.c index add92ac9f..42bc16ea0 100644 --- a/libbb/safe_strncpy.c +++ b/libbb/safe_strncpy.c @@ -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); } diff --git a/libpwdgrp/Kbuild b/libpwdgrp/Kbuild index 36a6ce393..9e60ef1e5 100644 --- a/libpwdgrp/Kbuild +++ b/libpwdgrp/Kbuild @@ -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 diff --git a/libpwdgrp/uidgid_get.c b/libpwdgrp/uidgid_get.c new file mode 100644 index 000000000..a2d02a84f --- /dev/null +++ b/libpwdgrp/uidgid_get.c @@ -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 +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 diff --git a/networking/httpd.c b/networking/httpd.c index ac9eac6bf..8f985774e 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -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 diff --git a/runit/Kbuild b/runit/Kbuild index 9fee84224..39a9b0229 100644 --- a/runit/Kbuild +++ b/runit/Kbuild @@ -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 diff --git a/runit/chpst.c b/runit/chpst.c index 1ee9b8d0f..da2f270e2 100644 --- a/runit/chpst.c +++ b/runit/chpst.c @@ -1,16 +1,9 @@ #include "busybox.h" -#include -#include -#include - -#include "uidgid.h" - -#include #include 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]); } diff --git a/runit/uidgid.c b/runit/uidgid.c deleted file mode 100644 index a8fec409d..000000000 --- a/runit/uidgid.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#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; -} diff --git a/runit/uidgid.h b/runit/uidgid.h deleted file mode 100644 index 1d47fe620..000000000 --- a/runit/uidgid.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef UIDGID_H -#define UIDGID_H - -#include - -struct uidgid { - uid_t uid; - gid_t gid[61]; - int gids; -}; - -extern unsigned uidgid_get(struct uidgid *, char *, unsigned); - -#endif