SVN: rc-scripts/branches/upstart_native/src: . Makefile.am setuidgid.c

jajcus jajcus at pld-linux.org
Fri May 7 13:24:41 CEST 2010


Author: jajcus
Date: Fri May  7 13:24:40 2010
New Revision: 11396

Added:
   rc-scripts/branches/upstart_native/src/setuidgid.c   (contents, props changed)
Modified:
   rc-scripts/branches/upstart_native/src/   (props changed)
   rc-scripts/branches/upstart_native/src/Makefile.am
Log:
- setuidgid tool added (from freedt) as upstart doesn't provide facilities to
  set user id for started jobs, 'su' sucks and using start-stop-daemon for
  this purpose would be an overkill.


Modified: rc-scripts/branches/upstart_native/src/Makefile.am
==============================================================================
--- rc-scripts/branches/upstart_native/src/Makefile.am	(original)
+++ rc-scripts/branches/upstart_native/src/Makefile.am	Fri May  7 13:24:40 2010
@@ -26,6 +26,7 @@
 	ppp-watch \
 	start-stop-daemon \
 	fstab-decode \
+	setuidgid \
 	usernetctl
 	
 EXTRA_PROGRAMS = \
@@ -66,4 +67,6 @@
 
 start_stop_daemon_SOURCES = start-stop-daemon.c
 
+setuidgid_SOURCES = setuidgid.c
+
 fstab_decode_SOURCES = fstab-decode.c

Added: rc-scripts/branches/upstart_native/src/setuidgid.c
==============================================================================
--- (empty file)
+++ rc-scripts/branches/upstart_native/src/setuidgid.c	Fri May  7 13:24:40 2010
@@ -0,0 +1,132 @@
+/*
+    Simple wrapper to run a command with different uid/gid.
+
+    Based on the implementation in freedt:
+       Copyright (C) 2003  Adam Sampson <azz at gnu.org>
+
+    2010-05-07 – Jacek Konieczny <jajcus> updated for standalone compilation
+    and included in PLD rc-scripts
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <string.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <grp.h>
+#include <limits.h>
+
+const char *progname = "setuidgid";
+const char *proghelp =
+	"Usage: setuidgid [OPTIONS] account command ...\n"
+	"Run a command under the uid and gid of an account.\n\n"
+	"-s        Also set supplementary groups\n";
+
+void die(const char *msg) {
+	fprintf(stderr, "%s: %s\n", progname, msg);
+	exit(1);
+}
+void die2(const char *msg1, const char *msg2) {
+	fprintf(stderr, "%s: %s: %s\n", progname, msg1, msg2);
+	exit(1);
+}
+void show_version() {
+	fprintf(stderr, "%s $Rev$ (PLD rc-scripts)\n", progname);
+}
+void version() {
+	show_version();
+	exit(0);
+}
+void help(int retval) {
+	show_version();
+	fprintf(stderr, "\n%s"
+		"-V        Show version information\n"
+		"-h        Show usage information\n", proghelp);
+	exit(retval);
+}
+
+int main(int argc, char **argv) {
+	struct passwd *p;
+	int use_supp = 0;
+
+	while (1) {
+		int c = getopt(argc, argv, "+V?hs");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 's':
+			use_supp = 1;
+			break;
+		case 'V':
+			version();
+		case 'h':
+		case '?':
+			help(0);
+		default:
+			help(1);
+		}
+	}
+
+	if ((argc - optind) < 2)
+		help(1);
+
+	p = getpwnam(argv[optind]);
+	if (!p)
+		die("no such account");
+	if (setgid(p->pw_gid) < 0)
+		die("unable to setgid");
+
+	if (use_supp) {
+		gid_t groups[NGROUPS_MAX];
+		size_t n = 0;
+
+		setgrent();
+		while (1) {
+			char **p;
+			struct group *g = getgrent();
+			if (g == NULL)
+				break;
+
+			for (p = g->gr_mem; *p != NULL; p++) {
+				if (strcmp(*p, argv[optind]) == 0) {
+					if (n >= NGROUPS_MAX)
+						die("too many groups");
+					groups[n++] = g->gr_gid;
+				}
+			}
+		}
+
+		if (setgroups(n, groups) < 0)
+			die("unable to setgroups");
+	} else {
+		if (setgroups(1, &p->pw_gid) < 0)
+			die("unable to setgroups");
+	}
+
+	if (setuid(p->pw_uid) < 0)
+		die("unable to setuid");
+
+	++optind;
+	execvp(argv[optind], &argv[optind]);
+	die2(argv[optind], "unable to exec");
+
+	return 0; /* NOTREACHED */
+}
+


More information about the pld-cvs-commit mailing list