setuid patch
Lisa Seelye
lisa@gentoo.org
Fri, 05 Sep 2003 18:13:29 -0400
--=-AH64vj0YabYs1WcjVtjM
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Attached is a patch made against the v1.38 memcached.c file to make
dropping root privileges possible (with the -u flag).
The patch is also available at:
http://dev.gentoo.org/~lisa/memcached/setuid.patch
--
Regards,
-Lisa
<Vix ulla tam iniqua pax, quin bello vel aequissimo sit potior>
--=-AH64vj0YabYs1WcjVtjM
Content-Disposition: attachment; filename=setuid.patch
Content-Type: text/x-patch; name=setuid.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Common subdirectories: cvs/CVS and cvs-diff/CVS
diff -uN cvs/Makefile.am cvs-diff/Makefile.am
--- cvs/Makefile.am 2003-08-27 14:52:29.000000000 -0400
+++ cvs-diff/Makefile.am 2003-09-05 16:19:49.000000000 -0400
@@ -1,9 +1,8 @@
bin_PROGRAMS = memcached
-memcached_SOURCES = memcached.c slabs.c items.c memcached.h assoc.c
+memcached_SOURCES = memcached.c slabs.c items.c memcached.h assoc.c setuid.c errors.h
DIST_SUBDIRS = doc
EXTRA_DIST = doc TODO
AM_CFLAGS=-DNDEBUG
-
Common subdirectories: cvs/api and cvs-diff/api
Common subdirectories: cvs/doc and cvs-diff/doc
diff -uN cvs/errors.h cvs-diff/errors.h
--- cvs/errors.h 1969-12-31 19:00:00.000000000 -0500
+++ cvs-diff/errors.h 2003-09-05 16:19:17.000000000 -0400
@@ -0,0 +1,10 @@
+/***************************************************************************
+ * errors.h
+ *
+ * Wed Aug 27 14:01:16 2003
+ * Lisa Seelye <lisa@gentoo.org>, for memcached
+ ****************************************************************************/
+
+#define MCD_ERROR_SETUID 100
+#define MCD_RUNNING_AS_ROOT 90
+#define MCD_NO_SPECIFIED_USERNAME 91
Common subdirectories: cvs/frontends and cvs-diff/frontends
diff -uN cvs/memcached.c cvs-diff/memcached.c
--- cvs/memcached.c 2003-09-05 16:11:53.000000000 -0400
+++ cvs-diff/memcached.c 2003-09-05 16:53:56.000000000 -0400
@@ -47,6 +47,7 @@
#endif
#include "memcached.h"
+#include "errors.h" // setuid errors live within
struct stats stats;
struct settings settings;
@@ -1250,13 +1251,16 @@
struct in_addr addr;
int lock_memory = 0;
int daemonize = 0;
-
+ char *username = "";
/* init settings */
settings_init();
/* process arguments */
- while ((c = getopt(argc, argv, "p:m:c:khivdl:")) != -1) {
+ while ((c = getopt(argc, argv, "u:p:m:c:khivdl:")) != -1) {
switch (c) {
+ case 'u':
+ username = optarg;
+ break;
case 'p':
settings.port = atoi(optarg);
break;
@@ -1339,9 +1343,13 @@
todelete = malloc(sizeof(item *)*deltotal);
delete_handler(0,0,0); /* sets up the event */
+ if (switch_user(username)) {
+ fprintf(stderr,"Failed to setuid %s\n",username);
+ exit(MCD_ERROR_SETUID);
+ }
+
/* enter the loop */
- event_loop(0);
+ event_loop(0);
return 0;
}
-
diff -uN cvs/setuid.c cvs-diff/setuid.c
--- cvs/setuid.c 1969-12-31 19:00:00.000000000 -0500
+++ cvs-diff/setuid.c 2003-09-05 16:19:17.000000000 -0400
@@ -0,0 +1,105 @@
+/***************************************************************************
+ * setuid.c
+ *
+ * Wed Aug 27 13:59:36 2003
+ * Lisa Seelye <lisa@gentoo.org>, for memcached
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <ctype.h>
+
+#include "errors.h" //setuid errors live within
+
+int switch_user(char *username);
+static int get_id(char *username, uid_t *uid, gid_t *gid);
+int is_superuser(void);
+
+int is_superuser(void) {
+ /* quickie to see if we're the superuser or not */
+ return ( (getuid() == 0 && getgid() == 0) );
+}
+
+static int get_id(char *username, uid_t *uid, gid_t *gid) {
+ /* Set uid and gid to the preferred user (found in setuid.h). Can either be
+ * numeric or a string, found in /etc/passwd.
+ */
+ struct passwd *pw;
+
+ if ((pw = getpwnam(username))) {
+ // Name exists
+ *uid = pw->pw_uid;
+ *gid = pw->pw_gid;
+ return 0;
+ }
+ /* something Bad happened, so send back an error */
+ return MCD_ERROR_SETUID;
+}
+
+int switch_user(char *username) {
+ /* Set uid and gid to the username specified in the function parameters.
+ *
+ * If the user starts memcached as root and fails to specify a username to
+ * switch to (`-u username'), we will return MCD_NO_SPECIFIED_USERNAME
+ *
+ * If memcached is started by a non-root user, we will attempt to switch to
+ * the username specified (`-u username'), and issue an error if we can't
+ * MCD_ERROR_SETUID.
+ *
+ * If the root user starts memcached and specifies `-u root' we will let
+ * them run as root.
+ */
+
+ uid_t uid; gid_t gid;
+
+
+ if (is_superuser()) {
+ // we are root
+ if (strcmp(username,"") == 0) {
+ // username isnt set and we're running as root. let's get outta here
+ fprintf(stderr,"No username specified with -u option!\n");
+ exit(MCD_NO_SPECIFIED_USERNAME);
+ }
+ else {
+ // We're root, but the user gave us a username to switch too.
+ int retval;
+ retval = get_id(username,&uid,&gid);
+ if (retval) {
+ //fprintf(stderr,"An error occurred while trying to setuid\nExiting...\n");
+ return retval;
+ } // Error in getting uid/gid.
+ } // we're okay for the setuid/setgid command Down Below
+ }
+ else {
+ //we are not root
+ if (strcmp(username,"") == 0) {
+ //no username, so we'll just run as $USER
+ return 0;
+ }
+ else {
+ /* Here we really have an option to let the user continue running as
+ * themselves, or to quit outright. I've decided to exit.
+ */
+ int retval;
+ retval = get_id(username,&uid,&gid);
+ if (retval) {
+ //fprintf(stderr,"An error occurred while trying to setuid\nExiting...\n");
+ return retval;
+ } // Error in getting uid/gid.
+ }
+ }
+ if (setgid(gid))
+ return MCD_ERROR_SETUID;
+ if (setuid(uid))
+ return MCD_ERROR_SETUID;
+
+ if ((getuid() == 0 || getgid() == 0) && strcmp(username,"root") != 0) {
+ /* We're still root, and we shouldn't be! */
+ return MCD_ERROR_SETUID;
+ }
+ return 0;
+}
Common subdirectories: cvs/website and cvs-diff/website
--=-AH64vj0YabYs1WcjVtjM--