I have just rewritten the rmuser perl script to C, it would be great if you could take a look at it and check if everything is ok.
How do I get this commited? -- Eirik Nygaard <[EMAIL PROTECTED]> PGP Key: 83C55EDE
/* ** -*- perl -*- ** Copyright 1995, 1996, 1997 Guy Helmer, Ames, Iowa 50014. ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer as ** the first lines of this file unmodified. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY GUY HELMER ``AS IS'' AND ANY EXPRESS OR ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL GUY HELMER BE LIABLE FOR ANY DIRECT, INDIRECT, ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ** rmuser - C programme to remove users ** ** Eirik Nygaard <[EMAIL PROTECTED]>, 08/08/02 ** ** $FreeBSD$ */ /* ** TODO: ** Add an at remove function */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/file.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <pwd.h> #include <dirent.h> #include <sys/uio.h> #include <sys/time.h> #include <sys/resource.h> #include <signal.h> #include <sys/wait.h> char passwd_file[] = "/etc/master.passwd"; char passwd_tmp[] = "/etc/ptmp"; char group_file[] = "/etc/group"; char new_group_file[] = "/etc/group.new"; char mail_dir[] = "/var/mail"; char crontab_dir[] = "/var/cron/tabs"; char path[] = "/bin:/sbin:/usr/bin:/usr/sbin"; int yes = 0; // Always yes? int removehomedir = 1; char *user = NULL; // User to delete char user2[400]; char answer[400]; int fp; FILE *fp2; char line[1024]; char homedir[1024]; struct passwd *password; struct stat sb; void usage(char *progname); void getuser(); void remove_files_from_dir(int uid, char *path); int recvnl( char *buf, int fd); void update_passwd(); void update_group(); void killuser(int uid, int gid); void del_mail(); void sig_handler1(); void sig_handler2(); void sig_handler3(); void sig_handler4(); int main(int argc, char **argv) { int ch, numbuf = 0; char string[1024], string2[1024], *p; struct sigaction sa; /* Check for root */ if (getuid() != 0) { printf("You must be root to run this program.\n"); _exit(-2); } sa.sa_handler = sig_handler1; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGINT, &sa, NULL); sa.sa_handler = sig_handler2; sigaction(SIGQUIT, &sa, NULL); sa.sa_handler = sig_handler3; sigaction(SIGHUP, &sa, NULL); sa.sa_handler = sig_handler4; sigaction(SIGTERM, &sa, NULL); /* Set the path we need */ setenv("PATH", path, 1); /* Set umode */ umask(022); /* Get command line arguments */ while ((ch = getopt(argc, argv, "yu:")) != -1) { switch (ch) { case 'y': yes = 1; break; case 'u': user = optarg; break; case '?': default: usage(argv[0]); } } if ((fp = open(passwd_file, O_RDONLY)) == NULL) { printf("Unable to open passwd file(%s).\n", passwd_file); _exit(-3); } fcntl(fp, F_SETFD, 1); if (flock(fp, LOCK_EX|LOCK_NB) == -1) { printf("Unable to lock passwd file(%s).\n", passwd_file); _exit(-4); } if (user == NULL) { getuser(); } while (recvnl(string, fp) != -1) { strcpy(string2, string); if ((p = strtok(string, ":")) != NULL) { if (strcasecmp(p, user) == 0) { printf("Matching password entry: \n\n"); printf("%s\n", string2); goto next1; } } } printf("No user by that name found.\n"); _exit(-6); next1: if (yes == 0) { printf("Is this the entry you wish to remove?(y/n) "); fgets(answer, sizeof(answer), stdin); if (strncmp(answer, "y", 1) != 0 && strncmp(answer, "Y", 1) != 0) { printf("User %s not removed.\n", user); _exit(1); } } if (flock(fp, LOCK_UN) == -1) { printf("Unable to unlock passwd file(%s).\n", passwd_file); _exit(-5); } close(fp); if ((password = getpwnam(user)) == NULL) { printf("Unable to get user info for user %s.\n", user); _exit(-11); } if (yes == 0) { printf("Remove homedir(%s)?(y/n) ", password->pw_dir); fgets(answer, sizeof(answer), stdin); if (strncmp(answer, "y", 1) == 0 || strncmp(answer, "Y", 1) == 0) removehomedir = 1; else removehomedir = 0; } else { removehomedir = 1; } strncpy(homedir, password->pw_dir, sizeof(homedir)); next2: lstat(homedir, &sb); if (removehomedir == 1) { if (!S_ISLNK(sb.st_mode) && !S_ISDIR(sb.st_mode)) { printf("Home %s is not a directory, so it won't be removed\n", homedir); removehomedir = 0; } if (S_ISLNK(sb.st_mode)) { numbuf = readlink(password->pw_dir, homedir, sizeof(homedir)); printf("%s\n", homedir); homedir[numbuf] = '\0'; goto next2; } if (sb.st_uid != password->pw_uid) { if (removehomedir == 1) printf("Home %s is not owned by %s, so it will not be removed.\n", homedir, user); removehomedir = 0; } } killuser(password->pw_uid, password->pw_gid); update_passwd(); update_group(); if (removehomedir == 1) { printf("Removeing home %s.\n", homedir); remove_files_from_dir(password->pw_uid, homedir); if (rmdir(homedir) == -1) printf("Warning: Unable to remove home %s - continuing.\n", homedir); } sprintf(line, "%s/%s", crontab_dir, user); if ((fp2 = fopen(line, "r")) != NULL) { fclose(fp2); if (unlink(line) == -1) printf("Warning: Unable to remove crontab file %s - continuing.\n", line); printf("Removeing users' crontab: "); sprintf(line, "/usr/bin/crontab -u %s -r", user); system(line); printf("done.\n"); } del_mail(); printf("Removing files belonging to %s from /tmp.\n", user); remove_files_from_dir(password->pw_uid, "/tmp"); printf("Removing files belonging to %s from /var/tmp.\n", user); remove_files_from_dir(password->pw_uid, "/var/tmp"); return 0; } void usage(char *progname) { printf("Usage: %s [-y] [-u username]\n", progname); _exit(-1); } void getuser() { printf("Enter login name for user to remove: "); fgets(user2, sizeof(user2), stdin); user2[strlen(user2) - 1] = '\0'; user = user2; } void remove_files_from_dir(int uid, char *path) { int Tmp; struct dirent *DirEntryPtr; DIR *DirPtr; struct stat Stat; char Path[1024]; DirPtr = opendir(path); while (1) { DirEntryPtr = readdir(DirPtr); if (DirEntryPtr == 0) break; if (strcmp(DirEntryPtr->d_name,".") != 0 && strcmp(DirEntryPtr->d_name,"..") != 0) { Path[0] = 0; strcat(Path,homedir); strcat(Path,"/"); strcat(Path,DirEntryPtr->d_name); Tmp = stat(Path,&Stat); if (S_ISDIR(Stat.st_mode)) { remove_files_from_dir(uid, Path); if (Stat.st_uid == uid) if (rmdir(Path) == -1) printf("Warning: Unable to remove dir %s - continuing.\n", Path); } if (Stat.st_uid == uid) { //printf("Removeing file %s\n", Path); if (unlink(Path) == -1) printf("Warning: unlink on %s failed - continuing.\n", Path); } } } return; } void update_passwd() { int fp_pw, fp2_pw; char string[1024], string2[1024]; int skipped = 0; if ((fp_pw = open(passwd_file, O_RDONLY|O_EXLOCK)) == -1) { printf("Warning: Unable to open %s, so can not remove the user - continuing.\n", passwd_file); return; } if ((fp2_pw = open(passwd_tmp, O_WRONLY|O_EXLOCK|O_CREAT, 0600)) == -1) { printf("Warning: Unable to open %s, so can not remove the user - continuing.\n", passwd_tmp); return; } sprintf(string2, "%s:", user); next3: while (recvnl(string, fp) != -1) { if (strncmp(string, "#", 1) == 0) goto next3; if (strncasecmp(string, string2, strlen(user) + 1) != 0) { write(fp2_pw, string, strlen(string)); write(fp2_pw, "\n", 1); } else { if (skipped == 1) { write(fp2_pw, string, strlen(string)); write(fp2_pw, "\n", 1); } //printf("Droped entry for %s\n", string); skipped = 1; } } if (skipped == 0) { printf("Whoops! Didn't find %s's entry second time around!\n", user); close(fp_pw); close(fp2_pw); sprintf(line, "/bin/rm -f %s", passwd_tmp); system(line); _exit(-10); } close(fp_pw); close(fp2_pw); /* Rebuild db */ sprintf(line, "/usr/sbin/pwd_mkdb -p %s", passwd_tmp); system(line); return; } void update_group() { char string[1024], string2[1024], string3[1024]; int fp_g, fp2_g, users; char *p, *p2; int a = 0; char group[1024], gid[1024], pass[1024], users2[1024], users3[1024]; if ((fp_g = open(group_file, O_RDONLY|O_EXLOCK)) == -1) { printf("Warning: Unable to open %s, so can not remove the user's group - continuing.\n", passwd_file); return; } if ((fp2_g = open(new_group_file, O_WRONLY|O_EXLOCK|O_CREAT, 0644)) == -1) { printf("Warning: Unable to open %s, so can not remove the user's group - continuing.\n", passwd_tmp); return; } sprintf(string2, "%s:", user); next4: while (recvnl(string, fp) != -1) { if (strncmp(string, "#", 1) == 0) goto next4; if (strncasecmp(string, string2, strlen(user) + 1) != 0) { // Check if user is in the group string3[0] = '\0'; strcpy(string3, string); for (p = strtok(string3, ":\n"); p != NULL; p = strtok(NULL, ":\n")) { if (a == 0) strcpy(group, p); if (a == 1) strcpy(pass, p); if (a == 2) strcpy(gid, p); if (a == 3) strcpy(users2, p); a++; } a = 0; users3[0] = '\0'; for (p = strtok(users2, ",\n"); p != NULL; p = strtok(NULL, ",\n")) { if (strcasecmp(user, p) != 0) { if (a == 0) { strcat(users3, p); a = 1; } else { strcat(users3, ","); strcat(users3, p); } } } sprintf(string3, "%s:%s:%s:%s\n", group, pass, gid, users3); /*printf("<%s>\n", string3);*/ write(fp2_g, string3, strlen(string3)); a = 0; } else { // Check if there is other users added to the group p = string; while (*p != ':') *p++; // Skip groupname *p++; while (*p != ':') *p++; // Skip password sectiona *p++; while (*p != ':') *p++; // Skip gid section *p++; strcpy(string3, p); for (p2 = strtok(string3, ","); p2 != NULL; p2 = strtok(NULL, ",")) { users = 1; } if (users == 1) { printf("Warning: Other users in group %s, not removing - continuing.\n", user); write(fp2_g, string, strlen(string)); } else { //printf("Droped entry %s\n", string); } } } close(fp_g); close(fp2_g); rename(new_group_file, group_file); return; } int recvnl( char *buf, int fd) { int bytes = 0; char buf2[2]; char buf3[1024]; buf3[0] = '\0'; while ( read(fd, buf2, 1) != 0) { buf2[1] = '\0'; if (strncmp(buf2, "\n", 1) == 0) { strcpy(buf, buf3); return bytes; } else if (strncmp(buf2, "\r", 1) != 0) { strcat(buf3, buf2); bytes++; } } return -1; } /* Kill users processes */ void killuser(int uid, int gid) { int pid; if (( pid = fork()) == 0) { setgid(gid); setuid(uid); if (getuid() != uid || getgid() != gid) { printf("Warning: Unable to set gid or uid, so I can't kill the users processes - continuing.\n"); _exit(-1); } kill(0, 15); sleep(1); kill(0, 9); _exit(0); } else { while (waitpid(-1,NULL,WNOHANG) != pid) ; } } void del_mail() { char string[1024]; FILE *file; sprintf(string, "%s/%s", mail_dir, user); if ((file = fopen(string, "r")) != NULL) { printf("Removing %s mail file.\n", user); fclose(file); if (unlink(string) == -1) printf("\tWarning: Unable to remove mail file %s.\n", string); } return; } void sig_handler1() { printf("\nCaught signal SIGINT -- cleaning up.\n"); unlink(passwd_tmp); unlink(new_group_file); _exit(5); } void sig_handler2() { printf("\nCaught signal SIGQUIT -- cleaning up.\n"); unlink(passwd_tmp); unlink(new_group_file); _exit(5); } void sig_handler3() { printf("\nCaught signal SIGHUP -- cleaning up.\n"); unlink(passwd_tmp); unlink(new_group_file); _exit(5); } void sig_handler4() { if (getuid() != 0) return; printf("\nCaught signal SIGTERM -- cleaning up.\n"); unlink(passwd_tmp); unlink(new_group_file); _exit(5); }
msg41746/pgp00000.pgp
Description: PGP signature