#include #include #include /* for exit(), atoi() */ #include #include #include #include /* for stat() */ #include /* for stat() */ #include /* for stat() */ #include /* for getpwnam_r() */ #include /* 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 allowed({ x("fixown", "+root", ""), x("fixown2", "+root", ""), x("skrewt", "+qmaild", ""), x("ward", "+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 todo; while (argc > 0) { string arg = argv[0]; argc--; argv++; todo.push_back(arg); } for (list::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 << " group 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); } } }