+/*
+ *
+ * CARNet System Admin Utility v1.26, 2003-12-05
+ *
+ * v1.00, 24 Jun 1996, first release
+ * v1.10, 17 Oct 1996, directories with ownership of specific group can be created and
+ * deleted, accounts 'srce' & 'admin' can be added (only)
+ * v1.15, 30 Oct 1996, admin program is now setuid!!! it gives off privileges
+ * when not needed
+ * v1.20, 30 Nov 1996, name changed, logging incorporated, access list, tty checking
+ * v1.21, 17 Dec 1996, shutdown asks for message and grace period, fixed all
+ * relative paths (security!), main menu slightly rearranged
+ * v1.22, 25 Feb 1997, Digital Unix 4.0 only: use user{add,del}(), fix checking for console
+ * v1.23, 10 Mar 1997, Again problems with OSF/DU and console checking
+ * v1.24, 12 Mar 1997, Rewritten code for console checking (I *hate* bloody Digital!!!)
+ * v1.25, 2002-04-28, Initial port to Debian GNU/Linux, limited functionality
+ * v1.26, 2003-12-05, quota for Linux. Only new style quotactl() on i386.
+ *
+ * Written by Zlatko Calusic
+ * Linux port Zoran Dzelajlija
+ *
+ * SRCE, University Computing Centre, Croatia
+ * CARNet, Croatian Academic and Research Network
+ *
+ */
+
+/* prototypes */
+
+#include "sysadmin.h"
+
+/* globals */
+
+char loginname[MAXLOGIN], group[MAXGROUP], username[MAXNAME], string[MAXSTR];
+char directory[MAXDIR], command[MAXCOMMAND], message[MAXMESS];
+int saveduid, grace;
+FILE *logfile;
+int conscheck = 1;
+
+char *authdir, *group_fallback_dir;
+
+
+/* body */
+
+void logger(char *fmt, ...)
+{
+ char *cptr, *whenptr;
+ va_list arg;
+ time_t when;
+
+ time(&when);
+ whenptr = ctime(&when);
+ if ((cptr = strchr(whenptr, '\n')))
+ *cptr = 0;
+ fprintf(logfile, "%s ", whenptr);
+ va_start(arg, fmt);
+ while (*fmt)
+ {
+ while (*fmt && *fmt != '%')
+ fputc(*fmt++, logfile);
+ fmt++;
+ switch(*fmt++)
+ {
+ case 's':
+ fprintf(logfile, "%s", va_arg(arg, char *));
+ break;
+ case 'd':
+ fprintf(logfile, "%d", va_arg(arg, int));
+ break;
+ default:
+ goto donefmt;
+ }
+ }
+ donefmt:
+ va_end(arg);
+ fputc('\n', logfile);
+ fflush(logfile);
+ return;
+}
+
+void priv(int pvar)
+{
+ int retval;
+
+ switch (pvar)
+ {
+ case ON:
+ retval = seteuid(0);
+ break;
+ case OFF:
+ default:
+ retval = seteuid(saveduid);
+ }
+ if (retval < 0)
+ {
+ fputs("\nInterna greska, izlazak iz programa!\n", stderr);
+ waitkey();
+ exit(0);
+ }
+ return;
+}
+
+int lockpw(void)
+{
+#if defined(ultrix)
+ if (!system("/bin/sh /etc/lockpw"))
+ return OK;
+ else
+ return ERROR;
+#elif defined(__osf__)
+ if (!mkdir("/etc/ptmp", 0700))
+ return OK;
+ else
+ return ERROR;
+#endif
+ return OK;
+}
+
+void unlockpw(void)
+{
+#if defined(ultrix)
+ system("/bin/sh /etc/unlockpw");
+#elif defined(__osf__)
+ rmdir("/etc/ptmp");
+#endif
+ return;
+}
+
+void consexit(void)
+{
+ fputs("\nProgram se moze pokrenuti samo s konzole.\nIzlazak iz programa!\n", stderr);
+ exit(1);
+}
+
+int getch(void)
+{
+ int ch = getchar();
+
+ if (ch != EOF && ch != '\n')
+ getchar();
+ return ch;
+}
+
+void clear(void)
+{
+#if defined(__SVR4) || defined(__osf__) || defined(__linux__)
+ system("/usr/bin/clear");
+#elif defined(ultrix)
+ system("/usr/ucb/clear");
+#endif
+ return;
+}
+
+void waitkey(void)
+{
+ printf("\nPritisnite <RETURN> za nastavak...");
+ while (getch() != '\n');
+ return;
+}
+
+void enter(char *var, int size)
+{
+ char *ptr;
+
+ fgets(var, size, stdin);
+ if ((ptr = strchr(var, '\n')))
+ *ptr = 0;
+ putchar('\n');
+ return;
+}
+
+void getuser(char *text)
+{
+ printf("%s\n\nUnesite korisnicko ime (login) > ", text);
+ enter(loginname, MAXLOGIN);
+ return;
+}
+
+void getgroup(char *text)
+{
+ if (*text)
+ printf("%s\n\n", text);
+ printf("Unesite ime grupe > ");
+ enter(group, MAXGROUP);
+ return;
+}
+
+int getname(void)
+{
+ int count = 0;
+
+ printf("Unesite ime i prezime korisnika > ");
+ enter(username, MAXNAME);
+ do
+ {
+ if (!isalnum(username[count]) && username[count] != ' ' && username[count] != '.' && username[count] != '-')
+ {
+ fputs("Unijeli ste nedozvoljene znakove u imenu korisnika!\n", stderr);
+ return ERROR;
+ }
+ count++;
+ } while (username[count]);
+ return OK;
+}
+
+int getdir(void)
+{
+ int len;
+ printf("Unesite puni put do direktorija > ");
+ enter(directory, MAXDIR);
+ if (strchr(directory, '.') || strstr(directory, "//"))
+ {
+ fputs("Unijeli ste nedozvoljene znakove!\n", stderr);
+ return ERROR;
+ }
+ len = strlen(directory);
+ if (strstr(directory, group_fallback_dir) != directory
+ || !strcmp(directory, group_fallback_dir))
+ {
+ fprintf(stderr, "Direktorij mora biti podredjen %s direktoriju.\n",
+ group_fallback_dir);
+ return ERROR;
+ }
+ if (directory[len] == '/')
+ directory[len] = 0;
+ return OK;
+}
+
+int getquota(int *soft, int *hard)
+{
+ printf("Unesite donji limit (soft) u KB > ");
+ enter(string, MAXSTR);
+ *soft = atoi(string);
+ if (*soft < 0 || *soft > MAXQUOTA)
+ goto error;
+ if (!*soft)
+ {
+ *hard = 0;
+ return OK;
+ }
+ printf("Unesite gornji limit (hard) u KB > ");
+ enter(string, MAXSTR);
+ *hard = atoi(string);
+ if (*hard >= 0 && *hard <= MAXQUOTA)
+ return OK;
+ error:
+ fputs("Unijeli ste nedozvoljenu vrijednost!\n", stderr);
+ return ERROR;
+}
+
+int testuser(int flag) {
+#if defined(__linux__)
+ char *forbidden[] = { "root", "daemon", "bin", "sys", "sync", "games", "man",
+ "lp", "mail", "news", "uucp", "proxy", "majordom",
+ "postgres",/* "www-data",*/ "backup", "msql", "operator",
+ "list", "irc", "gnats", "nobody", "snort", "ntop",
+ "mysql", "telnetd", "gdm", "freerad", "" };
+#elif defined(__SVR4)
+ char *forbidden[] = { "root", "daemon", "bin", "sys", "adm", "lp",
+ "smtp", "uucp", "nuucp", "listen", "nobody", "noaccess", "ftp",
+ "gopher", "http", "" };
+#elif defined(__osf__)
+ char *forbidden[] = { "root", "nobody", "nobodyV", "daemon", "bin",
+ "uucp", "uucpa", "auth", "cron", "lp", "tcb", "adm", "ris", "ftp",
+ "gopher", "http", "" };
+#elif defined(ultrix)
+ char *forbidden[] = { "root", "field", "nobody", "operator", "ris",
+ "daemon", "sys", "bin", "uucp", "uucpa", "sso", "news", "sccs",
+ "ingres", "ftp", "gopher", "http", "" };
+#endif
+ int count = 0;
+
+ if (!*loginname)
+ return ERROR;
+ if ((int) strlen(loginname) > 8) {
+ fputs("Maksimalna duzina korisnickog imena je 8 znakova!\n", stderr);
+ return ERROR;
+ }
+ do {
+ if (!islower(loginname[count]) && !isdigit(loginname[count])) {
+ fputs("Unijeli ste nedozvoljene znakove u korisnickom imenu!\n", stderr);
+ return ERROR;
+ }
+ count++;
+ } while (loginname[count]);
+ count = 0;
+ if (flag == ALL && (!strcmp(loginname, "srce") || !strcmp(loginname, "admin")))
+ goto fuckoff;
+ if (authdir) {
+ struct passwd *pwd;
+ pwd = getpwnam(loginname);
+ if (pwd && pwd->pw_dir)
+ if (strstr(pwd->pw_dir, authdir) != pwd->pw_dir)
+ goto fuckoff;
+ }
+ while (*forbidden[count]) {
+ if (!strcmp(forbidden[count], loginname)) {
+ fuckoff:
+ fputs("Nemate ovlasti za unesenog korisnika!\n", stderr);
+ return ERROR;
+ }
+ count++;
+ }
+ return OK;
+}
+
+int testgroup(void)
+{
+#if defined(__linux__)
+ char *forbidden[] = {"root", "daemon", "bin", "sys", "adm", "tty",
+ "disk", "lp", "mail", "news", "uucp", "proxy",
+ "kmem", "dialout", "fax", "voice", "cdrom", "tape",
+ "sudo", "audio", "dip", "majordom", "postgres",
+ "backup", "msql", "operator", "list", "irc",
+ "gnats", "shadow", "utmp", "video", "games",
+ "nogroup", "snort", "mysql", "telnetd", "gdm",
+ "freerad", "viruser", "" };
+#elif defined(__SVR4)
+ char *forbidden[] = { "root", "other", "bin", "sys", "adm", "uucp",
+ "mail", "tty", "lp", "nuucp", "staff", "daemon", "sysadmin",
+ "nobody", "noaccess", "wheel", "viruser", "" };
+#elif defined(__osf__)
+ char *forbidden[] = { "system", "daemon", "uucp", "mem", "kmem", "bin",
+ "sec", "mail", "terminal", "tty", "news", "opr", "auth", "lp", "lpr",
+ "backup", "cron", "sysadmin", "tape", "tcb", "adm", "operator",
+ "ris", "nobody", "nogroup", "wheel", "" };
+#elif defined(ultrix)
+ char *forbidden[] = { "system", "daemon", "uucp", "rsrv3", "bin", "tty",
+ "kmem", "authread", "news", "rsrv9", "staff", "ris", "guest",
+ "operator", "admin", "nobody", "wheel", "" };
+#endif
+ int count = 0;
+
+ if (!*group)
+ return ERROR;
+ if ((int) strlen(group) > 8) {
+ fputs("Maksimalna duzina imena grupe je 8 znakova!\n", stderr);
+ return ERROR;
+ } do {
+ if (!islower(group[count])) {
+ fputs("Unijeli ste nedozvoljene znakove u imenu grupe!\n", stderr);
+ return ERROR;
+ }
+ count++;
+ } while (group[count]);
+ count = 0;
+ while (*forbidden[count]) {
+ if (!strcmp(forbidden[count], group)) {
+ fputs("Nemate ovlasti za unesenu grupu!\n", stderr);
+ return ERROR;
+ }
+ count++;
+ }
+ if (authdir) {
+ struct group *grp = getgrnam(group);
+ if (grp && grp->gr_mem) {
+ struct passwd *pwd;
+ for (; *grp->gr_mem; grp->gr_mem++) {
+ pwd = getpwnam(*grp->gr_mem);
+ if (pwd && pwd->pw_dir) {
+ if (strstr(pwd->pw_dir, authdir) != pwd->pw_dir) {
+ fputs("Nemate ovlasti za unesenu grupu!\n", stderr);
+ return ERROR;
+ } else
+ break;
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+int system_default_shell_check(void)
+{
+ #ifndef __linux__
+ return 0;
+ #endif
+
+ struct stat statp;
+ statp.st_mode = 0;
+
+ (void) stat("/etc/default/useradd", &statp);
+ /* regular file? */
+ if (! statp.st_mode) return 0;
+ if (S_ISREG(statp.st_mode)) {
+ /* XXX maybe check file contents */
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void adduser(void)
+{
+ char fullhm[200];
+ char *shellopt="";
+ int l;
+ getuser("Dodavanje korisnika:");
+ if (testuser(NOTALL) == OK && getname() == OK) {
+ strncpy(fullhm, authdir ? authdir : HM, 199);
+ l = strlen(fullhm);
+ if (fullhm[l - 1] != '/') {
+ fullhm[l] = '/';
+ fullhm[l + 1] = '\0';
+ }
+ strncat(fullhm, loginname, 199);
+ logger("USER ADD: user %s, fullname %s", loginname, username);
+#if defined(__SVR4) || defined (__linux__)
+ if (!system_default_shell_check()) {
+ shellopt = "-s " DEFAULTSHELL;
+ }
+ sprintf(command, "/usr/sbin/useradd -m -d %s %s" \
+ " -c \"%s\" %s", fullhm, shellopt, username, loginname);
+ printf("%s\n", command);
+ priv(ON);
+ if (!system(command)) {
+ priv(OFF);
+ #if defined (__linux__)
+ /* Avoid race */
+ sync();
+ #endif /* __linux__ */
+ sprintf(command, "/usr/bin/passwd %s", loginname);
+ priv(ON);
+ system(command);
+ }
+#elif defined(__osf__)
+#if defined(DU4)
+ sprintf(command, "/usr/sbin/useradd -m -s " DEFAULTSHELL \
+ " -c \"%s\" %s", username, loginname);
+ priv(ON);
+ if (!system(command)) {
+ struct pr_passwd *pr;
+
+ if (!(pr = getprpwnam(loginname))) {
+ perror("getprpwnam");
+ goto problems;
+ }
+ pr->uflg.fg_lock = 1;
+ pr->uflg.fg_min = 1;
+ pr->ufld.fd_min = 0;
+ pr->uflg.fg_expire = 1;
+ pr->ufld.fd_expire = 0;
+ pr->uflg.fg_lifetime = 1;
+ pr->ufld.fd_lifetime = 0;
+ pr->uflg.fg_max_tries = 1;
+ pr->ufld.fd_max_tries = 0;
+ if (!putprpwnam(loginname, pr)) {
+ perror("putprpwnam");
+ goto problems;
+ }
+ sprintf(command, "/usr/bin/passwd %s", loginname);
+ system(command);
+ }
+#else
+ sprintf(command, "/usr/sbin/sysadm.adduser %s \"%s\"", loginname, username);
+ priv(ON);
+ system(command);
+#endif /* DU4 */
+#elif defined(ultrix)
+ sprintf(command, "/usr/etc/sysadm.adduser %s \"%s\"", loginname, username);
+ priv(ON);
+ system(command);
+#endif
+#if defined(DU4)
+ problems:
+#endif
+ priv(OFF);
+ }
+ waitkey();
+ return;
+}
+
+void rmuser(void)
+{
+ getuser("Brisanje korisnika:");
+ if (testuser(ALL) == OK) {
+ logger("USER REMOVE: user %s", loginname);
+#if defined(__SVR4) || defined(__linux__)
+ sprintf(command, "/usr/sbin/userdel -r %s", loginname);
+#elif defined(__osf__)
+ #if defined(DU4)
+ sprintf(command, "/usr/sbin/userdel -r %s", loginname);
+ #else
+ sprintf(command, "/usr/sbin/sysadm.removeuser %s", loginname);
+ #endif
+#elif defined(ultrix)
+ sprintf(command, "/usr/etc/sysadm.removeuser %s", loginname);
+#endif
+ priv(ON);
+ system(command);
+ priv(OFF);
+ }
+ waitkey();
+ return;
+}
+
+void chpass(void)
+{
+ getuser("Promjena korisnicke lozinke:");
+ if (testuser(NOTALL) == OK) {
+ logger("PASSWD CHANGE: user %s", loginname);
+ sprintf(command, "/usr/bin/passwd %s", loginname);
+ priv(ON);
+ system(command);
+ priv(OFF);
+ }
+ waitkey();
+ return;
+}
+
+void chquota(void)
+{
+ int soft, hard;
+ struct passwd *pwd;
+#if defined(__SVR4)
+ struct dqblk qval;
+ struct quotctl qstr;
+ struct stat statbuf;
+#elif defined(ultrix)
+ struct dqblk qval;
+ struct stat statbuf;
+#elif defined(__linux__)
+ #if defined(__i386__)
+ struct if_dqblk qval; /* sys/quota.h is wrong for 2.4.23/i386 */
+ #elif defined(__sparc__)
+ struct dqblk qval; /* 2.4.23/sparc is different */
+ #endif
+ struct stat statbuf;
+ struct mntent *mntp;
+ FILE *fp;
+ int dev;
+ char devname[MAXDIR], mountpoint[MAXDIR], greska[MAXDIR];
+ time_t now;
+ devname[0] = '\0';
+#endif
+
+ getuser("Promjena korisnicke quote:");
+ if (testuser(ALL) != OK) {
+ priv(OFF);
+ waitkey();
+ return;
+ }
+
+ if (!(pwd = getpwnam(loginname))) {
+ fputs("Ne postoji uneseni korisnik!\n", stderr);
+ waitkey();
+ return;
+ }
+
+#if defined(__linux__)
+ priv(ON);
+ if (stat(pwd->pw_dir, &statbuf) < 0) {
+ priv(OFF);
+ fputs("Korisnik nema maticni direktorij!\n", stderr);
+ waitkey();
+ return;
+ } else {
+ priv(OFF);
+ dev = statbuf.st_dev;
+ }
+
+ priv(ON);
+ if (!(fp = setmntent("/etc/mtab", "r"))) {
+ priv(OFF);
+ perror("setmntent");
+ waitkey();
+ return;
+ }
+ while (feof(fp) == 0) {
+ mntp = getmntent(fp);
+ if (!mntp) break;
+ /* ignore special fs' like proc, devfs... */
+ if (strncmp(mntp->mnt_fsname, "/dev", 4))
+ continue;
+ if (stat(mntp->mnt_fsname, &statbuf) < 0) {
+ priv(OFF);
+ perror("stat");
+ endmntent(fp);
+ waitkey();
+ return;
+ }
+ if (statbuf.st_rdev == dev) {
+ strncpy(devname, mntp->mnt_fsname, MAXDIR);
+ strncpy(mountpoint, mntp->mnt_dir, MAXDIR);
+ break;
+ }
+ }
+ endmntent(fp);
+ priv(OFF);
+
+ if(! strlen(devname))
+ {
+ fputs("Nije pronadjen device na kojem je korisnikov direktorij!\n", stderr);
+ waitkey();
+ return;
+ }
+
+ #ifdef __i386__
+ /* get previous quota values and update times */
+ priv(ON);
+ if (!quotactl(QCMD(Q_GETQUOTA, USRQUOTA), devname, pwd->pw_uid, (caddr_t) &qval)) {
+ priv(OFF);
+ time(&now);
+ if (qval.dqb_bsoftlimit && (
+ #if defined (__i386__)
+ qval.dqb_curspace
+ #elif defined (__sparc__)
+ qval.dqb_curblocks
+ #endif
+ /1024) >= qval.dqb_bsoftlimit) {
+ if (!qval.dqb_btime)
+ qval.dqb_btime = now + MAX_DQ_TIME;
+ }
+ else
+ qval.dqb_btime = 0;
+ if (qval.dqb_isoftlimit && qval.dqb_curinodes >= qval.dqb_isoftlimit) {
+ if (!qval.dqb_itime)
+ qval.dqb_itime = now + MAX_DQ_TIME;
+ }
+ else
+ qval.dqb_itime = 0;
+ } else {
+ priv(OFF);
+ fputs("Ne mogu utvrditi trenutne vrijednosti quote!\n", stderr);
+ waitkey();
+ return;
+ }
+ #endif
+#endif
+
+ if (getquota(&soft, &hard) == OK) {
+ logger("QUOTA CHANGE: user %s, soft %d, hard %d", loginname, soft, hard);
+#ifdef __SVR4
+ int i, count, fd;
+#endif
+ if (!soft)
+ fputs("Korisnik ce imati neogranicen pristup diskovnom prostoru!\n", stderr);
+#if defined(__linux__)
+ #if defined(__i386__)
+ /* Actually most of these are u_int64_t. */
+ qval.dqb_bsoftlimit = (u_int32_t) soft;
+ qval.dqb_bhardlimit = (u_int32_t) hard;
+ qval.dqb_isoftlimit = qval.dqb_ihardlimit = (u_int32_t) 0;
+ qval.dqb_btime = (time_t) now + MAX_DQ_TIME;
+ qval.dqb_itime = (time_t) now + MAX_IQ_TIME;
+ #if defined(__i386__)
+ /* Set limits and times */
+ qval.dqb_valid = QIF_LIMITS | QIF_TIMES;
+ #endif
+ priv(ON);
+ if (!
+ #if defined (__i386__)
+ quotactl(QCMD(Q_SETQUOTA, USRQUOTA), devname, pwd->pw_uid, (caddr_t) &qval)
+ #elif defined (__sparc__)
+ quotactl(QCMD(Q_SETQLIM, USRQUOTA), devname, pwd->pw_uid, (caddr_t) &qval)
+ #endif
+ )
+ #elif defined (__sparc__)
+ sprintf(command, "/usr/sbin/setquota %s -T %d %d %s", \
+ loginname, MAX_DQ_TIME, MAX_IQ_TIME, mountpoint);
+ printf("%s\n", command);
+ priv(ON);
+ if (!system(command)) {
+ priv(OFF);
+ /* fputs("Vremensko ogranicenje quote postavljeno.\n", stderr); */
+ }
+ else {
+ priv(OFF);
+ fputs("Nije uspjelo postavljanje vremenskog ogranicenja quote!\n", stderr);
+ waitkey();
+ return;
+ }
+ sprintf(command, "/usr/sbin/setquota %s %d %d %d %d %s", \
+ loginname, soft, hard, 0, 0, mountpoint);
+ printf("%s\n", command);
+ priv(ON);
+ if (!system(command))
+ #endif /* __sparc__ */
+ {
+ priv(OFF);
+ fputs("Quota uspjesno promijenjena.\n", stderr);
+ }
+ else {
+ priv(OFF);
+ if (errno == 3) {
+ sprintf(greska, "Quota nije ukljucena na filesystemu %s!\n", devname);
+ fputs(greska, stderr);
+ } else {
+ perror("quotactl");
+ }
+ }
+#elif defined(__SVR4)
+ qstr.uid = pwd->pw_uid;
+ for (count = 1; ; count++)
+ {
+ char *ptr;
+
+ strcpy(string, pwd->pw_dir);
+ for (i = 0; i < count; i++)
+ {
+ ptr = strrchr(string, '/');
+ if (ptr)
+ *ptr = 0;
+ else
+ goto noquota;
+ }
+ strcat(string, "/quotas");
+ priv(ON);
+ if (!stat(string, &statbuf) && (fd = open(string, O_RDWR)) > 0)
+ goto success;
+ priv(OFF);
+ }
+ noquota:
+ fputs("Nema quote na ovom sistemu!\n", stderr);
+ waitkey();
+ return;
+ success:
+ priv(OFF);
+ qval.dqb_bsoftlimit = (u_long) soft << 1;
+ qval.dqb_bhardlimit = (u_long) hard << 1;
+ qval.dqb_fsoftlimit = qval.dqb_fhardlimit = (u_long) 0;
+ qval.dqb_btimelimit = (u_long) DQ_BTIMELIMIT;
+ qval.dqb_ftimelimit = (u_long) DQ_FTIMELIMIT;
+ qstr.addr = (caddr_t) &qval;
+ qstr.op = Q_SETQLIM;
+ priv(ON);
+ if (!ioctl(fd, Q_QUOTACTL, &qstr))
+ fputs("Quota uspjesno promijenjena.\n", stderr);
+ else
+ perror("quotactl");
+#elif defined(__osf__)
+ qval.dqb_bsoftlimit = (u_long) soft << 1;
+ qval.dqb_bhardlimit = (u_long) hard << 1;
+ qval.dqb_isoftlimit = qval.dqb_ihardlimit = (u_int) 0;
+ qval.dqb_btime = (time_t) MAX_DQ_TIME;
+ qval.dqb_itime = (time_t) MAX_IQ_TIME;
+ priv(ON);
+ if (!quotactl(pwd->pw_dir, QCMD(Q_SETQUOTA, USRQUOTA), pwd->pw_uid, (char *) &qval))
+ fputs("Quota uspjesno promijenjena.\n", stderr);
+ else
+ perror("quotactl");
+#elif defined(ultrix)
+ priv(ON);
+ if (stat(pwd->pw_dir, &statbuf) < 0)
+ {
+ priv(OFF);
+ fputs("Korisnik nema maticni direktorij!\n", stderr);
+ waitkey();
+ return;
+ }
+ priv(OFF);
+ qval.dqb_bsoftlimit = (u_long) soft << 1;
+ qval.dqb_bhardlimit = (u_long) hard << 1;
+ qval.dqb_isoftlimit = qval.dqb_ihardlimit = (u_short) 0;
+ qval.dqb_bwarn = (u_char) MAX_DQ_WARN;
+ qval.dqb_iwarn = (u_char) MAX_IQ_WARN;
+ qval.dqb_curblocks = (u_long) 0;
+ qval.dqb_curinodes = (u_short) 0;
+ priv(ON);
+ if (!quota(Q_SETDLIM, pwd->pw_uid, statbuf.st_dev, (caddr_t) &qval))
+ fputs("Quota uspjesno promijenjena.\n", stderr);
+ else
+ perror("quota");
+#endif
+ }
+ priv(OFF);
+ waitkey();
+ return;
+}
+
+void opgroup(void)
+{
+ char ch;
+ int oldumask;
+
+ for (;;)
+ {
+ priv(OFF);
+ banner();
+ puts("Operacije nad grupama korisnika:\n");
+ puts("1 -- Kreiranje nove grupe");
+ puts("2 -- Dodavanje korisnika u grupu");
+ puts("3 -- Brisanje korisnika iz grupe");
+ puts("4 -- Brisanje grupe");
+ puts("5 -- Kreiranje direktorija (u koji grupa moze pisati)");
+ puts("6 -- Brisanje direktorija\n");
+ puts("7 -- Povratak u osnovni izbornik\n");
+ printf("Unesite odabir > ");
+ ch = getch();
+ clear();
+ switch(ch)
+ {
+ case '1':
+ getgroup("Kreiranje nove grupe:");
+ if (testgroup() == OK)
+ {
+ logger("GROUP CREATE: group %s", group);
+#if defined(__SVR4) || defined(__linux__)
+ sprintf(command, "/usr/sbin/groupadd %s", group);
+#elif defined(__osf__)
+ sprintf(command, "/usr/sbin/sysadm.addgroup %s", group);
+#elif defined(ultrix)
+ sprintf(command, "/usr/etc/sysadm.addgroup %s", group);
+#endif
+ priv(ON);
+ system(command);
+ priv(OFF);
+ }
+ waitkey();
+ break;
+ case '2':
+ getuser("Dodavanje korisnika u grupu:");
+ if (testuser(ALL) == OK)
+ {
+ if (getpwnam(loginname))
+ {
+ getgroup("");
+ if (testgroup() == OK)
+ {
+ FILE *readfp, *writefp;
+ char line[2048];
+ int found = 0;
+
+ logger("ADD USER TO GROUP: user %s, group %s", loginname, group);
+ priv(ON);
+ if (lockpw() == ERROR)
+ {
+ priv(OFF);
+#ifdef __osf__
+ fputs("Probajte malo kasnije, /etc/group je u upotrebi!\n", stderr);
+#endif
+ goto getout;
+ }
+ if (!(readfp = fopen("/etc/group", "rt")))
+ {
+ priv(OFF);
+ fputs("Ne mogu otvoriti /etc/group datoteku!\n", stderr);
+ goto getout;
+ }
+ unlink("/tmp/group");
+ if (!(writefp = fopen("/tmp/group", "wt")))
+ {
+ fclose(readfp);
+ priv(OFF);
+ fputs("Ne mogu otvoriti privremenu datoteku!\n", stderr);
+ goto getout;
+ }
+ while (fgets(line, 2048, readfp))
+ {
+ if (strstr(line, group) == line && line[strlen(group)] == ':')
+ {
+ char *ptr, left, right;
+
+ if ((ptr = strstr(line, loginname)))
+ {
+
+ left = *(ptr - 1);
+ right = *(ptr + strlen(loginname));
+ if ((left == ':' || left == ',') &&
+ (right == ',' || right == '\n'))
+ {
+ fclose(readfp);
+ fclose(writefp);
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Korisnik je vec u unesenoj grupi!\n", stderr);
+ goto getout;
+ }
+ }
+ if ((ptr = strrchr(line, '\n')))
+ *ptr = 0;
+ else
+ {
+ fclose(readfp);
+ fclose(writefp);
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Problem s datotekom /etc/group!\n", stderr);
+ goto getout;
+ }
+ if (*(ptr - 1) != ':')
+ strcat(line, ",");
+ strcat(line, loginname);
+ strcat(line, "\n");
+ found = 1;
+ }
+ fputs(line, writefp);
+ if (ferror(writefp))
+ {
+ fclose(readfp);
+ fclose(writefp);
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Problem prilikom pisanja privremene datoteke!\n", stderr);
+ goto getout;
+ }
+ }
+ fclose(readfp);
+ fclose(writefp);
+ if (found)
+ {
+ system("/bin/mv /tmp/group /etc/group");
+ priv(OFF);
+ fputs("Korisnik uspjesno dodan u grupu.\n", stderr);
+ }
+ else
+ {
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Ne postoji unesena grupa!\n", stderr);
+ }
+ }
+ }
+ else
+ fputs("Ne postoji uneseni korisnik!\n", stderr);
+ }
+ getout:
+ priv(ON);
+ unlockpw();
+ priv(OFF);
+ waitkey();
+ break;
+ case '3':
+ getuser("Brisanje korisnika iz grupe:");
+ if (testuser(ALL) == OK)
+ {
+ if (getpwnam(loginname))
+ {
+ getgroup("");
+ if (testgroup() == OK)
+ {
+ FILE *readfp, *writefp;
+ char line[2048];
+ int found = 0, empty = 0;
+
+ logger("REMOVE USER FROM GROUP: user %s, group %s", loginname, group);
+ priv(ON);
+ if (lockpw() == ERROR)
+ {
+ priv(OFF);
+#ifdef __osf__
+ fputs("Probajte malo kasnije, /etc/group je u upotrebi!\n", stderr);
+#endif
+ goto getout1;
+ }
+ if (!(readfp = fopen("/etc/group", "rt")))
+ {
+ priv(OFF);
+ fputs("Ne mogu otvoriti /etc/group datoteku!\n", stderr);
+ goto getout1;
+ }
+ unlink("/tmp/group");
+ if (!(writefp = fopen("/tmp/group", "wt")))
+ {
+ fclose(readfp);
+ priv(OFF);
+ fputs("Ne mogu otvoriti privremenu datoteku!\n", stderr);
+ goto getout1;
+ }
+ while (fgets(line, 2048, readfp))
+ {
+ if (strstr(line, group) == line && line[strlen(group)] == ':')
+ {
+ char *ptr, left, right;
+
+ if ((ptr = strstr(line, loginname)))
+ {
+ left = *(ptr - 1);
+ right = *(ptr + strlen(loginname));
+ if ((left == ':' || left == ',') &&
+ (right == ',' || right == '\n'))
+ goto ok;
+
+ }
+ fclose(readfp);
+ fclose(writefp);
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Korisnik nije u unesenoj grupi!\n", stderr);
+ goto getout1;
+ ok:
+ if (right != '\n')
+ strcpy(ptr, ptr + strlen(loginname) + 1);
+ else if (left != ':')
+ strcpy(ptr - 1, "\n");
+ else
+ {
+ empty = 1;
+ strcpy(ptr, "\n");
+ }
+ found = 1;
+ }
+ fputs(line, writefp);
+ if (ferror(writefp))
+ {
+ fclose(readfp);
+ fclose(writefp);
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Problem prilikom pisanja privremene datoteke!\n", stderr);
+ goto getout1;
+ }
+ }
+ fclose(readfp);
+ fclose(writefp);
+ if (found)
+ {
+ system("/bin/mv /tmp/group /etc/group"); /* JUNK */
+ priv(OFF);
+ fputs("Korisnik uspjesno obrisan iz grupe.\n", stderr);
+ if (empty)
+ fputs("U grupi nema vise ni jednog korisnika.\n", stderr);
+ }
+ else
+ {
+ unlink("/tmp/group");
+ priv(OFF);
+ fputs("Ne postoji unesena grupa!\n", stderr);
+ }
+ }
+ }
+ else
+ fputs("Ne postoji uneseni korisnik!\n", stderr);
+ }
+ getout1:
+ priv(ON);
+ unlockpw();
+ priv(OFF);
+ waitkey();
+ break;
+ case '4':
+ getgroup("Brisanje grupe:");
+ if (testgroup() == OK)
+ {
+ logger("GROUP REMOVE: group %s", group);
+#if defined(__SVR4) || defined(__linux__)
+ sprintf(command, "/usr/sbin/groupdel %s", group);
+#elif defined(__osf__)
+ sprintf(command, "/usr/sbin/sysadm.removegroup %s", group);
+#elif defined(ultrix)
+ sprintf(command, "/usr/etc/sysadm.removegroup %s", group);
+#endif
+ priv(ON);
+ system(command);
+ priv(OFF);
+ }
+ waitkey();
+ break;
+ case '5':
+ oldumask = umask(002);
+ if (getdir() == OK)
+ {
+ getgroup("Grupa u cije vlasnistvo zelite staviti direktorij:");
+ if (testgroup() == OK)
+ {
+ struct group *grpptr;
+ int i, status;
+
+ grpptr = getgrnam(group);
+ if (!grpptr)
+ {
+ fputs("Trazena grupa ne postoji!\n", stderr);
+ goto donedir;
+ }
+ logger("DIRECTORY CREATE: directory %s, group %s", directory, group);
+ for (i = 1;;i++)
+ {
+ while (directory[i] && directory[i] != '/')
+ i++;
+ if (directory[i])
+ {
+ directory[i] = 0;
+ priv(ON);
+ status = mkdir(directory, 0755);
+ if (status < 0 && errno != EEXIST)
+ {
+ priv(OFF);
+ perror("mkdir");
+ goto donedir;
+ }
+ priv(OFF);
+ directory[i] = '/';
+ }
+ else
+ {
+ priv(ON);
+ status = mkdir(directory, 0775);
+ if (status < 0 && errno != EEXIST)
+ {
+ perror("mkdir");
+ goto donedir;
+ }
+ errno = 0;
+ if (chown(directory, (uid_t) -1, grpptr->gr_gid) < 0)
+ perror("chown");
+ else
+ fputs("Direktorij uspjesno kreiran.\n", stderr);
+ goto donedir;
+ }
+ }
+ }
+ }
+ donedir:
+ priv(OFF);
+ umask(oldumask);
+ waitkey();
+ break;
+ case '6':
+ if (getdir() == OK)
+ {
+ logger("DIRECTORY REMOVE: directory %s", directory);
+ priv(ON);
+ if (rmdir(directory) < 0)
+ perror("rmdir");
+ else
+ fputs("Direktorij uspjesno obrisan.\n", stderr);
+ priv(OFF);
+ }
+ waitkey();
+ break;
+ case '7':
+ case 'Q':
+ case 'q':
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+void shutdown(void)
+{
+ int count = 0;
+
+ printf("Unesite poruku za korisnike > ");
+ enter(message, MAXMESS);
+ do
+ {
+ if (!isalpha(message[count]) && !isspace(message[count]) && !isdigit(message[count]) && message[count] != '.' && message[count] != ',' && message[count] != '_' && message[count] != '-' && message[count] != '=')
+ {
+ priv(OFF);
+ fputs("Unijeli ste nedozvoljene znakove u poruci!\n", stderr);
+ waitkey();
+ return;
+ }
+ count++;
+ } while (message[count]);
+ printf("\nUnesite vrijeme kroz koje ce se racunalo zaustaviti (1 - 60 min) > ");
+ enter(string, MAXSTR);
+ grace = atoi(string);
+ if (grace < MINGRACE || grace > MAXGRACE)
+ {
+ priv(OFF);
+ fprintf(stderr, "Unijeli ste vrijeme koje je nula, negativno ili preveliko!\n");
+ waitkey();
+ return;
+ }
+#if defined(__SVR4)
+ grace *= 60;
+#endif
+ puts("Pokrenuta je procedura za zaustavljanje racunala!\n");
+ logger("SHUTDOWN!");
+#if defined(__SVR4)
+ sprintf(command, "/usr/sbin/shutdown -i0 -y -g%d \"%s\"", grace, message);
+#elif defined(__osf__) || defined (__linux__)
+ sprintf(command, "/sbin/shutdown -h +%d %s", grace, message);
+#elif defined(ultrix)
+ sprintf(command, "/bin/shutdown -h +%d %s", grace, message);
+#endif
+ priv(ON);
+ system(command);
+ priv(OFF);
+ loop:
+ sleep(10);
+ goto loop;
+ waitkey();
+ return;
+}
+
+void manual(void)
+{
+ FILE* manual;
+ char line[256];
+ int count = 0;
+
+ logger("MANUAL READ");
+ priv(ON);
+ if (!(manual = fopen(MANFILE, "rt")))
+ {
+ priv(OFF);
+ fputs("Uputstva nisu instalirana!\n", stderr);
+ waitkey();
+ return;
+ }
+ priv(OFF);
+ while (fgets(line, 256, manual))
+ {
+ fputs(line, stdout);
+ if (count++ == 21)
+ {
+ waitkey();
+ clear();
+ count = 0;
+ }
+ }
+ fclose(manual);
+ waitkey();
+ return;
+}
+
+void banner(void)
+{
+ clear();
+ puts(VERSION);
+ return;
+}
+
+void console_check(char *name)
+{
+ char *cptr;
+ int oncon = 0;
+ struct stat statbuf;
+ struct utmp entry;
+ FILE *fp;
+
+ priv(OFF);
+ if (isatty(0))
+ cptr = ttyname(0);
+ else
+ {
+ fprintf(stderr, "\nProblem s terminalom.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ if (!cptr || strcmp(cptr, CONSOLE))
+ {
+ if (stat(CONSOLE, &statbuf) < 0)
+ {
+ fprintf(stderr, "\nNe mogu provjeriti vlasnistvo /dev/console.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ if (statbuf.st_uid == saveduid)
+ return;
+#if defined(__SVR4)
+ else
+ consexit();
+#endif
+
+#if defined(__osf__) || defined(ultrix) || defined(__linux__)
+ if (strstr(cptr, "/dev/") == cptr)
+ strcpy(cptr, cptr + 5);
+ fp = fopen(UTMP_FILE, "r");
+ if (!fp)
+ {
+ priv(OFF);
+ fprintf(stderr, "\nNe mogu otvoriti utmp datoteku.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ while (fread(&entry, sizeof(entry), 1, fp))
+ {
+ #if defined(__linux__)
+ entry.ut_line[UT_LINESIZE-1] = 0;
+ entry.ut_user[UT_NAMESIZE-1] = 0;
+ entry.ut_host[UT_HOSTSIZE-1] = 0;
+ #else
+ entry.ut_line[8] = 0;
+ entry.ut_name[8] = 0;
+ entry.ut_host[16] = 0;
+ #endif
+ #if defined (__linux__)
+ if (entry.ut_type == DEAD_PROCESS)
+ continue;
+ if (strncmp(entry.ut_line, cptr, UT_LINESIZE-1))
+ continue;
+ if (!strncmp(entry.ut_line, "tty", 3) && \
+ entry.ut_line[3] >= '0' && \
+ entry.ut_line[3] <= '9' && \
+ !strncmp(entry.ut_user, name, UT_NAMESIZE-1)) {
+ oncon = 1;
+ break;
+ }
+ else if (!strncmp(entry.ut_host, ":0", 2) && \
+ !strncmp(entry.ut_user, name, UT_NAMESIZE-1)) {
+ oncon = 1;
+ break;
+ }
+ else
+ break; /* pravi tty, a nije na konzoli */
+ #else
+ if (strncmp(entry.ut_line, cptr, 8))
+ continue;
+ if (!strncmp(entry.ut_line, ":0", 2) && !strncmp(entry.ut_name, name, 8))
+ {
+ oncon = 1;
+ break;
+ }
+ if (!strncmp(entry.ut_host, ":0.0", 8) || !strncmp(entry.ut_host, "local", 8)) {
+ oncon = 1;
+ break;
+ }
+ #endif /* __linux__ */
+ }
+ fclose(fp);
+ if (!oncon)
+ consexit();
+#endif
+ }
+ return;
+}
+
+
+int main(int argc, char **argv)
+{
+ char ch, *cptr;
+ int allowed;
+ FILE *aclfile;
+ FILE *conffile;
+ struct passwd *acl = NULL;
+ char adminlogin[64], adminfull[1024];
+ char *p;
+
+#if defined(DU4)
+ set_auth_parameters(argc,argv);
+#endif
+ umask(022);
+ putenv("IFS=\" \"");
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ saveduid = getuid();
+ setuid(0);
+ chmod(LOGFILE, 0600);
+ chmod(ACLFILE, 0600);
+ chown(LOGFILE, 0, -1);
+ chown(ACLFILE, 0, -1);
+ if (!(logfile = fopen(LOGFILE, "a")))
+ {
+ priv(OFF);
+ perror("fopen");
+ fprintf(stderr, "\nNe mogu otvoriti log datoteku.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ if (saveduid)
+ {
+ if (!(aclfile = fopen(ACLFILE, "r")))
+ {
+ priv(OFF);
+ perror("fopen");
+ fprintf(stderr, "\nNe mogu otvoriti datoteku kontrole pristupa.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ allowed = 0;
+ while (fgets(string, MAXSTR, aclfile))
+ {
+ if (*string == '#')
+ continue;
+ authdir = group_fallback_dir = NULL;
+ for (p = string; *p && !isspace(*p); p++);
+ cptr = p;
+ if (*p && *p != '\n')
+ {
+ while (isspace(*p))
+ ++p;
+ authdir = p;
+ while (*p && !isspace(*p))
+ ++p;
+ if (*p != '\n')
+ {
+ *p++ = '\0';
+ group_fallback_dir = p;
+ while (*p && !isspace(*p))
+ ++p;
+ *p = '\0';
+ group_fallback_dir = strdup(group_fallback_dir);
+ }
+ else
+ *p = '\0';
+ }
+ *cptr = 0;
+ if ((acl = getpwnam(string)) && acl->pw_uid == saveduid)
+ {
+ if (authdir)
+ authdir = strdup(authdir);
+ else
+ authdir = NULL;
+ allowed = 1;
+ break;
+ }
+ }
+ fclose(aclfile);
+ if (!group_fallback_dir)
+ group_fallback_dir = authdir ? authdir : HM;
+ if (!allowed)
+ {
+ priv(OFF);
+ fprintf(stderr, "\nNemate dozvolu za koristenje programa.\nIzlazak iz programa!\n");
+ exit(1);
+ }
+ priv(ON);
+ if (!(conffile = fopen(OPTFILE, "r"))) {
+ priv(OFF);
+/* perror("fopen");
+ fprintf(stderr, "Ne mogu otvoriti datoteku s konfiguracijskim opcijama.\n");
+ sleep(2);
+*/ }
+ else {
+ priv(OFF);
+ while (fgets(string, MAXSTR, conffile)) {
+ p = &string[strlen(string)-1];
+ if (*p == '\n')
+ *p = '\0';
+ if (!strncmp(string, CONF_NOCONSOLE, MAXSTR-1))
+ conscheck = 0;
+ }
+ fclose(conffile);
+ }
+
+ if (!authdir && conscheck)
+ console_check(acl->pw_name);
+ }
+ else
+ {
+ authdir = NULL;
+ group_fallback_dir = HM;
+ acl = getpwuid(0);
+ }
+ if (acl && acl->pw_name)
+ strcpy(adminlogin, acl->pw_name);
+ else
+ strcpy(adminlogin, "(none)");
+ if (acl && acl->pw_gecos)
+ strcpy(adminfull, acl->pw_gecos);
+ else
+ strcpy(adminfull, "NULL");
+ logger("ADMIN START: admin %s (%s)", adminlogin, adminfull);
+ for (;;)
+ {
+ priv(OFF);
+ banner();
+ puts("1 -- Dodavanje korisnika");
+ puts("2 -- Brisanje korisnika");
+ puts("3 -- Promjena lozinke korisnika");
+ puts("4 -- Promjena quote korisnika\n");
+ puts("5 -- Operacije nad grupama korisnika\n");
+ puts("6 -- Zaustavljanje i gasenje racunala\n");
+ puts("7 -- Pomoc\n");
+ puts("8 -- Izlazak iz administracijskog programa\n");
+ printf("Unesite odabir > ");
+ ch = getch();
+ clear();
+ switch(ch)
+ {
+ case '1':
+ adduser();
+ break;
+ case '2':
+ rmuser();
+ break;
+ case '3':
+ chpass();
+ break;
+ case '4':
+ chquota();
+ break;
+ case '5':
+ opgroup();
+ break;
+ case '6':
+ shutdown();
+ break;
+ case '7':
+ case 'h':
+ case '?':
+ manual();
+ break;
+ case '0':
+ case '8':
+ case 'Q':
+ case 'q':
+ clear();
+ logger("ADMIN END: admin %s (%s)", adminlogin, adminfull);
+ fclose(logfile);
+ exit(0);
+ default:
+ break;
+ }
+ }
+}