httpd: add -u user[:grp] support
authorDenis Vlasenko <vda.linux@googlemail.com>
Thu, 5 Oct 2006 22:50:22 +0000 (22:50 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Thu, 5 Oct 2006 22:50:22 +0000 (22:50 -0000)
12 files changed:
coreutils/id.c
e2fsprogs/ext2fs/version.c
include/libbb.h
include/usage.h
libbb/safe_strncpy.c
libpwdgrp/Kbuild
libpwdgrp/uidgid_get.c [new file with mode: 0644]
networking/httpd.c
runit/Kbuild
runit/chpst.c
runit/uidgid.c [deleted file]
runit/uidgid.h [deleted file]

index 9e49999cdb1dfd8270541c0cda33652cf8ef12d1..9d605325c12a153db6d273925746efdf223c7e15 100644 (file)
 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);
        }
index 882e121d42e5d21c337777b7a74c18fe94734215..d2981e867ebe2e653b8bf0d870d5a518c148108b 100644 (file)
@@ -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;
 
index ed1d780fd3153dda862526f4e34ff3ed3233131d..adfeca5900d852c2f2e341084ea3ea3136f9c881 100644 (file)
@@ -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);
 
index 34b0566cd4ed4d297fecdbf2a3e320d6ebf41869..c9e501903617e03214c09128196990fe361920dd 100644 (file)
@@ -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 \
index add92ac9f735c096ca5187c7b2130c891e64434b..42bc16ea0d07acfddf27f148b36477881dfd6820 100644 (file)
@@ -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);
 }
index 36a6ce39313cb3f7d85f31de6936553f2e1c4566..9e60ef1e50b3e0ec12a388b64833af5d60ce0cbd 100644 (file)
@@ -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 (file)
index 0000000..a2d02a8
--- /dev/null
@@ -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
index ac9eac6bfc997d86b090ce9e1a08ddd9f6159c1f..8f985774e86dac21de9bc1ec02c48e05948fc33d 100644 (file)
@@ -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
 
index 9fee84224abf4bde708710f91ba3fffb53e9c23f..39a9b02291073cedebc4bea1eafc39228d140873 100644 (file)
@@ -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
index 1ee9b8d0f5b60fb0b6c606466ad19bf792762897..da2f270e296e7ddc1b52b5987c3d311da3482d7f 100644 (file)
@@ -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]);
 }
diff --git a/runit/uidgid.c b/runit/uidgid.c
deleted file mode 100644 (file)
index a8fec40..0000000
+++ /dev/null
@@ -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;
-}
diff --git a/runit/uidgid.h b/runit/uidgid.h
deleted file mode 100644 (file)
index 1d47fe6..0000000
+++ /dev/null
@@ -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