This is popauth.c in view mode; [Download] [Up]
/* * Copyright (c) 1997 by Qualcomm Incorporated. */ /* */ /* popauth.c - manipulate POP authorization DB */ #include <config.h> #ifdef GDBM # include <gdbm.h> #else # if HAVE_NDBM_H # include <ndbm.h> # else # if HAVE_DBM_H # include <dbm.h> # endif # endif #endif #include <pwd.h> #include <stdio.h> #ifdef __STDC__ #include <stdlib.h> #include <stdarg.h> #else #include <varargs.h> #endif #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #ifndef HAVE_BCOPY #define bcopy(src,dest,len) (void) (memcpy(dest,src,len)) #define bzero(dest,len) (void) (memset(dest, (char)NULL, len)) #define bcmp(b1,b2,n) memcmp(b1,b2,n) #endif #ifndef HAVE_INDEX # define index(s,c) strchr(s,c) # define rindex(s,c) strrchr(s,c) #endif #include <flock.h> #if HAVE_STRINGS_H #include <strings.h> #endif #if HAVE_SYS_FILE_H #include <sys/file.h> #endif #ifdef BSDI #define BSD44_DBM #endif #ifdef NEED_STRERROR char *strerror(); #endif #define UID_T uid_t static struct swit { char *name; } switches[] = { #define INITSW 0 "init", #define LISTSW 1 "list", #define USERSW 2 "user", #define DELESW 3 "delete", NULL, }; static char *program; #ifdef __STDC__ static void adios(const char *fmt, ...) #else static void adios(va_alist) va_dcl #endif { va_list ap; #ifndef __STDC__ char *fmt; #endif (void) fprintf(stderr, "%s: ", program); #ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); fmt = va_arg(ap, char *); #endif (void) vfprintf(stderr, fmt, ap); (void) fprintf(stderr, "\n"); va_end(fmt); exit(1); /*NOTREACHED*/ } #ifndef HAVE_STRDUP #include <stddef.h> char * strdup(str) char *str; { int len; char *copy; len = strlen(str) + 1; if (!(copy = malloc((u_int)len))) return((char *)NULL); bcopy(str, copy, len); return(copy); } #endif /* * Obscure password so a cleartext search doesn't come up with * something interesting. * */ char * obscure(string) char *string; { unsigned char *cp, *newstr; cp = newstr = (unsigned char *)strdup(string); while (*cp) { *cp++ ^= 0xff; } return((char *)newstr); } /* Use GNU_PASS for longer passwords on systems that support termios */ #ifndef GNU_PASS char *getpass(); #else /* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* It is desireable to use this bit on systems that have it. The only bit of terminal state we want to twiddle is echoing, which is done in software; there is no need to change the state of the terminal hardware. */ #include <stdio.h> #include <termios.h> #include <unistd.h> #ifndef TCSASOFT #define TCSASOFT 0 #endif #ifdef SSIZET typedef SSIZET ssize_t; #endif char * getpass (prompt) #if defined(HPUX) char *prompt; #else const char *prompt; #endif { FILE *in, *out; struct termios t; int echo_off; static char *buf = NULL; static size_t bufsize = 0; ssize_t nread; /* Try to write to and read from the terminal if we can. If we can't open the terminal, use stderr and stdin. */ in = fopen ("/dev/tty", "w+"); if (in == NULL) { in = stdin; out = stderr; } else out = in; /* Turn echoing off if it is on now. */ if (tcgetattr (fileno (in), &t) == 0) { if (t.c_lflag & ECHO) { t.c_lflag &= ~ECHO; echo_off = tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0; t.c_lflag |= ECHO; } else echo_off = 0; } else echo_off = 0; /* Write the prompt. */ fputs (prompt, out); fflush (out); /* Read the password. */ #ifdef NO_GETLINE bufsize = 256; buf = (char *)malloc(256); nread = (fgets(buf, (size_t)bufsize, in) == NULL) ? 1 : strlen(buf); rewind(in); fputc('\n', out); #else nread = __getline (&buf, &bufsize, in); #endif if (nread < 0 && buf != NULL) buf[0] = '\0'; else if (buf[nread - 1] == '\n') /* Remove the newline. */ buf[nread - 1] = '\0'; /* Restore echoing. */ if (echo_off) (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t); if (in != stdin) /* We opened the terminal; now close it. */ fclose (in); return buf; } #endif /* ARGSUSED */ main (argc, argv) int argc; char *argv[]; { UID_T myuid; int flags, i, delesw = 0, initsw = 0, insist, listsw = 0, popuser = 0; long clock; char *bp, *cp, *usersw = NULL, buf[100], obuf[100]; struct passwd *pw; datum key, value; #ifdef GDBM GDBM_FILE db; char apop_file[BUFSIZ]; #else DBM *db; char apop_dir[BUFSIZ]; #ifndef BSD44_DBM char apop_pag[BUFSIZ]; #endif #endif int f; program = argv[0]; argv++; argc--; while (argc > 0) { cp = argv[0]; if (*cp == '-') { int i, v; i = 0; v = -1; for(i = 0; switches[i].name; i++) { if(strcmp(&cp[1], switches[i].name) == 0) { v = i; break; } } cp++; switch (v) { default: adios ("-%s unknown option", cp); case INITSW: initsw = 1, listsw = 0; delesw = 0; break; case LISTSW: listsw = 1, initsw = 0; delesw = 0; break; case DELESW: delesw = 1, initsw = 0; listsw = 0; if (argc < 2 || argv[1][0] == '-') adios ("missing argument to %s", argv[0]); usersw = argv[1]; argc--; argv++; break; case USERSW: if (argc < 2 || argv[1][0] == '-') adios ("missing argument to %s", argv[0]); usersw = argv[1]; argc--; argv++; if (delesw) fprintf(stderr, "Warning: user '%s' will now be deleted\n", usersw); break; } } else adios ("usage: %s [[-init]|[-list]|[-user name]|[-delete name]]", program); argc--; argv++; } #ifndef APOP adios ("not compiled with APOP option"); #else myuid = getuid(); if ((pw = getpwnam (POPUID)) == NULL) adios ("\"%s\": user-id unknown", POPUID); if (pw->pw_uid == myuid) popuser = 1; if (myuid && !popuser && (delesw || initsw || listsw || (usersw != NULL))) adios("Only superuser or user '%s' can perform the requested function", POPUID); if (myuid && initsw) adios("Only superuser can init the database"); #ifdef GDBM (void) strncpy(apop_file, APOP, sizeof(apop_file) - 1); apop_file[sizeof(apop_file)-1] = '\0'; #else (void) strncpy(apop_dir, APOP, sizeof(apop_dir) - 5); #ifdef BSD44_DBM (void) strcat(apop_dir, ".db"); #else (void) strncpy(apop_pag, APOP, sizeof(apop_pag) - 5); (void) strcat(apop_pag, ".pag"); (void) strcat(apop_dir, ".dir"); #endif #endif if (delesw) { if (myuid && !popuser) adios ("Only root or %s may delete entries", POPUID); #ifdef GDBM if ((db = gdbm_open(apop_file,512,GDBM_WRITER,0,0)) == NULL) #else if ((db = dbm_open (APOP, O_RDWR, 0)) == NULL) #endif adios ("%s: unable to open POP authorization DB", APOP); key.dsize = strlen (key.dptr = usersw) + 1; #ifdef GDBM value = gdbm_fetch(db, key); #else value = dbm_fetch(db, key); #endif if (value.dptr == NULL) adios("User '%s' not found in apop database", usersw); #ifdef GDBM if (gdbm_delete(db,key) < 0) #else if (dbm_delete(db, key) < 0) #endif adios("Unable to delete user '%s' from apop database", usersw); #ifdef GDBM gdbm_close (db); #else dbm_close (db); #endif exit (0); } if (initsw) { struct stat st; setuid(myuid); #ifdef GDBM if (stat (apop_file, &st) != -1) #else if (stat (apop_dir, &st) != -1) #endif { char ibuf[30]; printf("Really initialize POP authorization DB? "); if(fgets(ibuf, sizeof(ibuf), stdin) == NULL || ibuf[0] != 'y') exit (1); #ifdef GDBM (void) unlink (apop_file); #else (void) unlink (apop_dir); # ifndef BSD44_DBM (void) unlink (apop_pag); # endif #endif } #ifdef GDBM if ((db = gdbm_open (apop_file, 512, GDBM_WRCREAT, 0600, 0)) == NULL) adios ("unable to create POP authorization DB: %s", strerror(errno)); gdbm_close (db); if (chown (apop_file, pw->pw_uid, pw->pw_gid) == -1) adios ("error setting ownership of POP authorization for %s : %s", apop_file, strerror(errno)); #else if ((db = dbm_open (APOP, O_RDWR | O_CREAT, 0600)) == NULL) adios ("unable to create POP authorization DB: %s", strerror(errno)); dbm_close (db); if (chown (apop_dir, pw->pw_uid, pw->pw_gid) == -1 #ifndef BSD44_DBM || chown (apop_pag, pw->pw_uid, pw->pw_gid) == -1 #endif ) adios ("error setting ownership of POP authorization DB: %s", strerror(errno)); #endif exit (0); } #ifdef GDBM if ((db = gdbm_open (apop_file, 512, GDBM_READER, 0, 0)) == NULL) #else if ((db = dbm_open (APOP, O_RDONLY, 0)) == NULL) #endif adios ("unable to open POP authorization DB: %s", strerror(errno)); /* this one opens again the already open file by gdbm_open, or dbm_open above #ifdef GDBM if ((f = open (apop_file, listsw ? O_RDONLY : O_RDWR)) == -1) adios ("%s: unable to open POP authorization DB", apop_file); if (flock (f, LOCK_SH) == -1) adios ("%s: unable to lock POP authorization DB", apop_file); #else if ((f = open (apop_dir, listsw ? O_RDONLY : O_RDWR)) == -1) adios ("%s: unable to open POP authorization DB", apop_dir); if (flock (f, LOCK_SH) == -1) adios ("%s: unable to lock POP authorization DB", apop_dir); #endif */ #ifdef GDBM f = db->dummy[4]; /* file descriptor for apop_file */ if (flock (f, LOCK_SH) == -1) { gdbm_close (db); adios ("%s: unable to lock POP authorization DB", apop_file); } #else f = db->dbm_dirf; /* file descriptor for apop_dir */ if (flock (f, LOCK_SH) == -1) { dbm_close (db); adios ("%s: unable to lock POP authorization DB", apop_dir); } #endif if (listsw) { if (usersw) { key.dsize = strlen (key.dptr = usersw) + 1; #ifdef GDBM value = gdbm_fetch (db, key); #else value = dbm_fetch (db, key); #endif if (value.dptr == NULL) adios ("no such entry in POP authorization DB"); printf ("%s\n", key.dptr); } else #ifdef GDBM for (key = gdbm_firstkey (db); key.dptr; key = gdbm_nextkey (db,key)) #else for (key = dbm_firstkey (db); key.dptr; key = dbm_nextkey (db)) #endif { printf ("%s", key.dptr); #ifdef GDBM value = gdbm_fetch (db, key); #else value = dbm_fetch (db, key); #endif if (value.dptr == NULL) printf (" - no information?!?\n"); else { printf ("\n"); } } #ifdef GDBM gdbm_close (db); #else dbm_close (db); #endif exit (0); } if (usersw == NULL) { if ((pw = getpwuid(myuid)) == NULL) adios("Sorry, don't know who uid %d is.", myuid); usersw = pw->pw_name; } else { if ((pw = getpwnam(usersw)) == NULL) adios("Sorry, don't know who uid %s is.", usersw); usersw = pw->pw_name; } fprintf (stderr, "Changing POP password for %s.\n", usersw); key.dsize = strlen (key.dptr = usersw) + 1; #ifdef GDBM value = gdbm_fetch (db, key); #else value = dbm_fetch (db, key); #endif if (myuid && !popuser && value.dptr != NULL) { if (((i = strlen(strncpy(obuf, getpass("Old password:"), sizeof(obuf)))) == 0) || ((value.dsize - 1) != i) || (strncmp(obuf, value.dptr, i) && strncmp(obuf, obscure(value.dptr), i))) { adios("Sorry, password entered incorrectly\n"); } } #ifdef GDBM gdbm_close (db); #else dbm_close (db); #endif #ifdef lint flags = 0; #endif /* lint */ for (insist = 0; insist < 2; insist++) { int i; char c; if (insist) printf ("Please use %s.\n", flags == 1 ? "at least one non-numeric character" : "a longer password"); if (((i = strlen(strncpy(buf, getpass("New password:"), sizeof(buf)))) == 0) || !strncmp(buf, obuf, i)) { fprintf (stderr, "Password unchanged.\n"); exit (1); } flags = 0; for (cp = buf; c = *cp++;) if (c >= 'a' && c <= 'z') flags |= 2; else if (c >= 'A' && c <= 'Z') flags |= 4; else if (c >= '0' && c <= '9') flags |= 1; else flags |= 8; if ((flags >= 7 && i >= 4) || ((flags == 2 || flags == 4) && i >= 6) || ((flags == 3 || flags == 5 || flags == 6) && i >= 5)) break; } if (strcmp(buf, getpass("Retype new password:"))) { fprintf (stderr, "Mismatch - password unchanged.\n"); exit (1); } #ifdef GDBM if ((db = gdbm_open(apop_file, 512, GDBM_WRITER, 0, 0)) == NULL) #else if ((db = dbm_open(APOP, O_RDWR, 0)) == NULL) #endif adios("%s: unable to open POP authorization DB", APOP); /* if (flock(f, LOCK_EX) == -1) adios("%s: unable to lock POP authorization DB", #ifdef GDBM apop_file #else apop_dir #endif ); */ #ifdef GDBM if (flock(f, LOCK_EX) == -1) { gdbm_close(db); adios("%s: unable to lock POP authorization DB", apop_file); } #else if (flock(f, LOCK_EX) == -1) { dbm_close(db); adios("%s: unable to lock POP authorization DB", apop_dir); } #endif key.dsize = strlen (key.dptr = usersw) + 1; value.dptr = obscure(buf); value.dsize = strlen(value.dptr) + 1; #ifdef GDBM if (gdbm_store (db, key, value, GDBM_REPLACE)) adios ("POP authorization DB may be corrupt?!?"); gdbm_close (db); #else if (dbm_store (db, key, value, DBM_REPLACE)) adios ("POP authorization DB may be corrupt?!?"); dbm_close (db); #endif #endif exit (0); /* NOTREACHED */ } #ifdef NEED_STRERROR char * strerror(e) int e; { extern char *sys_errlist[]; extern int sys_nerr; if(e < sys_nerr) return(sys_errlist[e]); else return("unknown error"); } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.