summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJohn Denker <jsd@av8n.com>2012-07-31 13:12:26 -0700
committerJohn Denker <jsd@av8n.com>2012-07-31 14:34:25 -0700
commit158def7ed5c5100456d05150670cfebc3bc2ddd1 (patch)
treed7ccefab5c44dd705e977e7bdd8f4bccd490b9da /tools
parent6b22bf70dbdffb38b58e6b69421d432651680a71 (diff)
more-or-less secure way to use setuid features
Diffstat (limited to 'tools')
-rw-r--r--tools/fixown.c139
-rw-r--r--tools/makefile23
2 files changed, 157 insertions, 5 deletions
diff --git a/tools/fixown.c b/tools/fixown.c
new file mode 100644
index 0000000..087e7c9
--- /dev/null
+++ b/tools/fixown.c
@@ -0,0 +1,139 @@
+#include <iostream>
+#include <iomanip>
+#include <stdlib.h> /* for exit(), atoi() */
+#include <list>
+#include <map>
+#include <sstream>
+
+#include <sys/types.h> /* for stat() */
+#include <sys/stat.h> /* for stat() */
+#include <unistd.h> /* for stat() */
+#include <pwd.h> /* for getpwnam_r() */
+#include <grp.h> /* for getgrnam_r() */
+
+#include "utils.h" /* for basename() */
+
+using namespace std;
+
+class owngroup{
+public:
+ string owner;
+ string group;
+};
+
+#define x(a,b,c) make_pair(a, owngroup({b,c}))
+
+map<string,owngroup> allowed({
+ x("fixown", "+root", ""),
+ x("fixown2", "+root", ""),
+ x("skrewt", "+qmaild", ""),
+ x("ltgrey", "+qmaild", ""),
+ x("greylist", "+qmaild", ""),
+ x("wripper", "", "+daemon"),
+});
+
+pid_t mypid;
+string progname;
+string progid;
+
+int main(int _argc, char** _argv){
+ int argc(_argc);
+ char** argv(_argv);
+ {
+ progname = *argv++; argc--;
+ mypid = getpid();
+ stringstream binder;
+ binder << basename(progname) << "[" << mypid << "]";
+ progid = binder.str();
+ }
+
+ list<string> todo;
+
+ while (argc > 0) {
+ string arg = argv[0]; argc--; argv++;
+ todo.push_back(arg);
+ }
+
+ for (list<string>::const_iterator ptr = todo.begin();
+ ptr != todo.end(); ptr++){
+ string file = *ptr;
+ if (allowed.find(file) == allowed.end()){
+ cerr << progid << " not on the allowed list: " << file << endl;
+ exit(1);
+ }
+ struct stat statbuf;
+ int rslt = stat(file.c_str(), &statbuf);
+ if (rslt < 0) {
+ cerr << progid << " stat failed for "
+ << file << " : ";
+ perror(0);
+ exit(1);
+ }
+ mode_t mode = statbuf.st_mode;
+ string own = allowed[file].owner;
+ string grp = allowed[file].group;
+ if (0) cout << oct << mode
+ << " " << own
+ << " " << grp
+ << dec << endl;
+
+ if (own[0] == '+') {
+ own = own.substr(1);
+ mode |= S_ISUID;
+ }
+ if (grp[0] == '+') {
+ grp = grp.substr(1);
+ mode |= S_ISGID;
+ }
+ //xx cout << oct << mode << dec << endl << endl;
+
+ uid_t own_num = statbuf.st_uid;
+ gid_t grp_num = statbuf.st_gid;
+
+ if (own.length()){
+ struct passwd pw;
+ struct passwd* ppw;
+ long int size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ char scratch[size];
+ getpwnam_r(own.c_str(), &pw,
+ scratch, size, &ppw);
+ if (ppw == 0) {
+ cerr << progid << " user not found: " << own << endl;
+ exit(1);
+ }
+ own_num = pw.pw_uid;
+ }
+ //xxx cout << own << " --> " << own_num << endl;
+
+ if (grp.length()){
+ struct group gr;
+ struct group* pgr;
+ long int size = sysconf(_SC_GETPW_R_SIZE_MAX);
+ char scratch[size];
+ getgrnam_r(grp.c_str(), &gr,
+ scratch, size, &pgr);
+ if (pgr == 0) {
+ cerr << progid << " user not found: " << grp << endl;
+ exit(1);
+ }
+ grp_num = gr.gr_gid;
+ }
+ //xxx cout << grp << " --> " << grp_num << endl;
+
+ rslt = chown(file.c_str(), own_num, grp_num);
+ if (rslt < 0) {
+ cerr << progid << " chown failed for "
+ << file << " : ";
+ perror(0);
+ exit(1);
+ }
+ chmod(file.c_str(), mode);
+ if (rslt < 0) {
+ cerr << progid << " chmod failed for "
+ << file << " : ";
+ perror(0);
+ exit(1);
+ }
+
+ }
+}
diff --git a/tools/makefile b/tools/makefile
index 6594ca8..723d756 100644
--- a/tools/makefile
+++ b/tools/makefile
@@ -1,5 +1,5 @@
-CC= /usr/bin/g++ -Wall -g -I $(HOME)/lib/include
-
+CC= /usr/bin/g++
+CFLAGS = -std=gnu++0x -Wall -g -I $(HOME)/lib/include
#?? exhibits = checkpassword.patch hi-q.c pido.c pop3.conf smtp.conf \
#?? smtp.rules spamc-zap.patch spamd qmail
@@ -15,7 +15,7 @@ qmain = pido.c hi-q.c skrewt.c hi-test.c mail-scan.c greylist.c wripper.c
qprogs = $(qmain:%.c=%)
# sources for other main programs:
-moremain = wripper.c bash-c.c ltgrey.c
+moremain = wripper.c bash-c.c ltgrey.c fixown.c
moreprogs = $(moremain:%.c=%)
nonmain = libltgrey.c
@@ -32,23 +32,36 @@ beware_other = checkpassword.c spamc.c
| sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
[ -s $@ ] || rm -f $@'
-all: $(qprogs) $(moreprogs)
+all: $(qprogs) $(moreprogs) fixown2
show:
: --- $(qprogs) +++ $(moreprogs)
+fixown: fixown.o utils.o
+ $(CC) $^ -o $@
+ chmod o-rwx $@
+ ./fixown2 $@
+
+fixown2: fixown.o utils.o
+ $(CC) $^ -o $@
+ chmod o-rwx $@
+ ./fixown $@
+
skrewt: skrewt.o utils.o
$(CC) $^ -lboost_filesystem-mt -lboost_system -o $@
+ ./fixown $@
greylist: greylist.o utils.o
$(CC) $^ -lboost_filesystem-mt -lboost_system -o $@
+ ./fixown $@
ltgrey: ltgrey.o utils.o libltgrey.o
$(CC) $^ -lboost_filesystem-mt -lboost_system -o $@
+ ./fixown $@
wripper: wripper.o
$(CC) $^ -o $@
- chgrp daemon $@ && chmod g+s $@ || true
+ ./fixown $@
mail-scan: mail-scan.o utils.o
$(CC) $^ -lboost_regex -o $@