/* * Mail a tous les adherents de CRANS. * * Copyright (c) 1999 Association CRANS. * * Auteur: Olivier Saut * * A faire : sécuriser les strcat, faire la gestion des bats avec la libregex... */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define kPCGuestUID 502 #define kCorbeauUID 536 #define kNobodyUID 65534 #define kRealUsers 500 /* Prototypes */ int mk_tmpfile(); void edit(); int sendmail(char *name); void help(); int isValidUID(uid_t uid); void mySig_handler(int iInt); /* Variables globales */ char *gTempname; uid_t gCurrent_UID; uid_t gUid_start; uid_t gUid_stop; int gVerbose; int gSimulate; /* Programme principal */ int main(int argc, char *argv[]) { struct passwd *passwd_ent; struct passwd *user; char buf[1024]; extern char *optarg; extern int optind; int ch ; struct stat begin, end; sig_t previous_handler; char tildefn[MAXPATHLEN]; int fd=-1; gUid_start=kRealUsers; gUid_stop=kNobodyUID; gVerbose=0; gSimulate=0; while ((ch = getopt(argc, argv, "svhf:d:a:")) != -1) switch (ch) { case 'h': help(); break; case 'v': gVerbose=1; break; case 's': gVerbose=1; gSimulate=1; break; case 'f': gTempname=optarg; if ((fd = open(optarg, O_RDONLY, 0)) < 0) { (void)fprintf(stderr, "myname: %s: %s\n", optarg, strerror(errno)); exit(1); } break; case 'd': gUid_start=atoi(optarg); break; case 'a': gUid_stop=atoi(optarg); break; } argc -= optind; argv += optind; previous_handler = signal(SIGTERM & SIGINT,(sig_t) mySig_handler); if(previous_handler==SIG_ERR) { (void)fprintf(stderr,"Erreur lors de l'installation du sighandler."); exit(EXIT_FAILURE); } if(gVerbose) fprintf(stdout,"mailCRANS by OS. Version 0.1\n"); if(fd==-1) { fd=mk_tmpfile(); user=getpwuid(getuid()); sprintf(buf,"From: %s\nSubject: \nReply-To: \nContent-Type: text/plain; charset=iso-8859-1", user->pw_name); if (write (fd,(void *)buf,strlen(buf)) < 0) { close(fd); fprintf(stderr, "Erreur en écriture."); exit(EXIT_FAILURE); } (void) fsync(fd); if(fstat(fd,&begin)) { perror("Erreur stat(1)"); close(fd); exit(EXIT_FAILURE); } (void) edit(); if(stat(gTempname,&end)) { perror("Erreur stat(2)"); close(fd); exit(EXIT_FAILURE); } if (begin.st_mtime == end.st_mtime) { warnx("No changes made : exiting"); close(fd); (void)unlink(gTempname); exit(EXIT_FAILURE); } } setpwent(); while((int)(passwd_ent=(struct passwd *)getpwent())) { gCurrent_UID=passwd_ent->pw_uid; if(isValidUID(gCurrent_UID)) if(sendmail(passwd_ent->pw_name )) { exit(EXIT_FAILURE); } else usleep(250000); } endpwent(); (void)unlink(gTempname); /* Bon on efface le fichier parasite */ (void)strcpy((char *)tildefn,gTempname); (void)strcat((char *)tildefn,"~"); if(!access(tildefn,F_OK)) (void)unlink(tildefn); return 0; } int isValidUID(uid_t uid) { if(uidgUid_stop) return 0; if((uid==kPCGuestUID)|| (uid==kCorbeauUID) || (uid==kNobodyUID)) return 0; return 1; } void mySig_handler(int iInt) { (void) fprintf(stdout,"\n Signal %d intercepté.\n",iInt); (void) fprintf(stderr,"Le programme s'est arreté sur l'uid : %d\n",gCurrent_UID); exit(EXIT_SUCCESS); } int mk_tmpfile() { int fd; char p[MAXPATHLEN]; p[MAXPATHLEN-1]='\0'; strcpy(p, "/tmp/EAll.XXXXXX"); if ((fd = mkstemp(p)) == -1) err(1, "%s", p); gTempname = malloc(strlen(p)); (void)strncpy(gTempname,p,strlen(p)); if(gVerbose) fprintf(stdout,"Tempfile name : %s\n",gTempname); return (fd); } void edit() { int pstat; int editpid; char *p, *editor; if (!(editor = getenv("EDITOR"))) editor = _PATH_VI; if ((p = strrchr(editor, '/'))) ++p; else p = editor; if (!(editpid = fork())) { errno = 0; execlp(editor, p, gTempname, NULL); _exit(errno); } for (;;) { editpid = waitpid(editpid, (int *)&pstat, WUNTRACED); errno = WEXITSTATUS(pstat); (void) fprintf(stderr,"\n *** %d ***\n",WEXITSTATUS(pstat)); if (editpid == -1) exit(EXIT_FAILURE); else if (WIFSTOPPED(pstat)) raise(WSTOPSIG(pstat)); else if (WIFEXITED(pstat) && errno == 0) break; else exit(EXIT_FAILURE); } editpid = -1; } int sendmail(char *pw_name) { int res=0; char *buff; int length; buff=malloc(1024); buff[1023]='\0'; buff[0]='\0'; (void)strcat((char *)buff,(const char *)"cat "); (void)strcat(buff,(const char *) gTempname); (void)strcat(buff, " | sendmail "); (void)strcat(buff, pw_name); if(gVerbose) fprintf(stdout,"\n ** %s ** \n", buff); if(!gSimulate) res=system(buff); return res; } void help() { fprintf(stdout,"usage: mailCRANS [-v] [-s] [-f filename] [-{d,a} uid]\n"); fprintf(stdout," -v : mode bavard\n"); fprintf(stdout," -f filename : envoie le fichier en argument\n"); fprintf(stdout," (rajouter une ligne Subject: en première ligne du fichier pour avoir un sujet\n"); fprintf(stdout," -d uid : envoie à partir de l'UID argument\n"); fprintf(stdout," -a uid : arrete après l'UID argument\n"); fprintf(stdout," -s : mode simulation."); exit(EXIT_SUCCESS); }