Memcached TODO list?
Lisa Marie Seelye
lisa@gentoo.org
Fri, 29 Aug 2003 00:16:18 -0400
--=-nCdao2ZCRaW7NKj58fmr
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
On Thu, 2003-08-28 at 05:12, Anatoly Vorobey wrote:
> - have a command-line switch "-u user" meaning "assume identity of user
> when run as root"
> - refuse to run as root unless the switch is given.
To this end, here is a revised patch.
If it fails to be presented in a text/plain format, it can be found at
http://dev.gentoo.org/~lisa/memcached/setuid1.patch (note the '1')
How is this? It passes my local tests. Not sure if I got the logic
down right... check the comments in the setuid.c file for how I
interpreted it.
--
Regards,
-Lisa
<Vix ulla tam iniqua pax, quin bello vel aequissimo sit potior>
--=-nCdao2ZCRaW7NKj58fmr
Content-Disposition: attachment; filename=setuid1.patch
Content-Type: text/x-patch; name=setuid1.patch; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
Common subdirectories: cvs/.deps and cvs-diff/.deps
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-08-27 13:48:31.000000000 -0400
@@ -1,6 +1,6 @@
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 setuid.h errors.h
DIST_SUBDIRS = doc
EXTRA_DIST = doc TODO
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-08-28 15:41:23.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
diff -uN cvs/memcached.c cvs-diff/memcached.c
--- cvs/memcached.c 2003-08-27 14:52:30.000000000 -0400
+++ cvs-diff/memcached.c 2003-08-29 00:10:59.000000000 -0400
@@ -47,6 +47,7 @@
#endif
#include "memcached.h"
+#include "errors.h" //setuid error codes live within
struct stats stats;
struct settings settings;
@@ -1249,13 +1250,18 @@
struct in_addr addr;
int lock_memory = 0;
int daemonize = 0;
+ int setuid_error = 0;
+ char *username = "";
/* init settings */
- settings_init();
+ 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;
@@ -1338,9 +1344,18 @@
todelete = malloc(sizeof(item *)*deltotal);
delete_handler(0,0,0); /* sets up the event */
+ /* I think here would be a good place to discard (or attempt to) our
+ * priveledges.
+ */
+
+ setuid_error = switch_user(username);
+ if (setuid_error) {
+ fprintf(stderr,"Failed to setuid %s\n",username);
+ exit(MCD_ERROR_SETUID);
+ }
+
/* enter the loop */
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-08-29 00:08:33.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
--=-nCdao2ZCRaW7NKj58fmr--