home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.sgi.admin
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!eagle!ZoSo.lerc.nasa.gov!fsfacca
- From: fsfacca@ZoSo.lerc.nasa.gov (Tony Facca)
- Subject: Re: letting users choose their login shells
- Message-ID: <1992Dec29.151509.16858@eagle.lerc.nasa.gov>
- Sender: news@eagle.lerc.nasa.gov
- Nntp-Posting-Host: zoso.lerc.nasa.gov
- Organization: NASA Lewis Research Center [Cleveland, Ohio]
- References: <1hkv9vINNba9@tamsun.tamu.edu>
- Date: Tue, 29 Dec 1992 15:15:09 GMT
- Lines: 442
-
- vamsee@abgen.tamu.edu (Vamsee Lakamsani) writes:
- >Is there a way to let the users change their shell and finger information
- >on the SGIs. I used "/bin/chsh" and "/bin/chfn" on the SUNs. Does anybody
- >know if something similar exists for an SGI(4.0.5A) ?
- >
- >Vamsee
-
- Actually, the source for chsh is available:
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: Makefile READ_ME chfn.1 chsh.1 chsh.c
- # Wrapped by fsfacca@ZoSo on Tue Dec 29 10:13:13 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(397 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- XCFLAGS=-O
- XDEST=/usr/local/bin
- XDOC_DEST=/usr/catman/local/cat1
- X
- Xchfn chsh: chsh.o
- X cc $(CFLAGS) chsh.o -o chsh
- X -rm chfn
- X ln chsh chfn
- X
- Xinstall: chsh chfn
- X @echo Warning: you must be superuser to do this.
- X -rm $(DEST)/chsh $(DEST)/chfn
- X cp chsh $(DEST)/chsh
- X ln $(DEST)/chsh $(DEST)/chfn
- X chown root $(DEST)/chsh
- X chmod 4711 $(DEST)/chsh
- X cp chsh.1 $(DOC_DEST)/chsh.1
- X cp chfn.1 $(DOC_DEST)/chfn.1
- END_OF_FILE
- if test 397 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'READ_ME' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'READ_ME'\"
- else
- echo shar: Extracting \"'READ_ME'\" \(1567 characters\)
- sed "s/^X//" >'READ_ME' <<'END_OF_FILE'
- XThis program was originally written by K. Richard Magill,
- Xand posted to mod.sources. Since it contained a few
- XSYS5 dependencies, a *serious* security bug, and no sanity
- Xchecks at all, I decided to hack it up a bit.
- X
- XIt now checks a given shell for existence and executability (only
- Xby looking at the mode, sorry), and it honors the standard
- X(as far as I know) algorithm for locking password files.
- X
- XThe serious security bug was the following: Imagine a user called
- Xhacky doing the following:
- Xchsh hacky '/bin/sh
- Xdummy::0:0::/:'
- X
- XSo, if you've installed it already, better remove it *fast*.
- X
- XAlso, some cosmetic changes were made: If no username is given, the
- Xcurrent user is assumed, and if no shell/realname is given, the
- Xold one is printed, and a new one asked.
- X
- XINSTALLATION:
- X
- XFirst, look at the defines at the top in chsh.c. If your system has
- Xputpwent(), remove the #define NOPUTPWENT.
- X
- XSecond, if you don't mind people playing with other people's
- Xshells and names, remove the #define SECURE.
- X
- XThird, KEEP YOUR HANDS OFF the #define DEBUG.
- X
- XI tried this on a mucho hacked up 11/34 running V7, so it is not
- Xmore than sensible that you test it before letting it anywhere near
- Xthe password file.
- X
- XNow, compile it, run it a few times (not as super-user), and,
- Xwhen you're satisfied, remove the #define DEBUG.
- X
- XNow you can type make install, to re-compile and install it.
- X(Don't forget to look at the Makefile to make sure all
- Xpaths are as you would like them).
- X
- X--
- X Jack Jansen, jack@htsa.UUCP (or jack@mcvax.UUCP)
- X ...!mcvax!vu44!htsa!jack
- X The shell is my oyster.
- END_OF_FILE
- if test 1567 -ne `wc -c <'READ_ME'`; then
- echo shar: \"'READ_ME'\" unpacked with wrong size!
- fi
- # end of 'READ_ME'
- fi
- if test -f 'chfn.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'chfn.1'\"
- else
- echo shar: Extracting \"'chfn.1'\" \(829 characters\)
- sed "s/^X//" >'chfn.1' <<'END_OF_FILE'
- X.TH CHFN 1 Local
- X.SH NAME
- Xchfn \- change user's real name
- X.SH SYNOPSIS
- X.B chfn
- X[ user [ realname ] ]
- X.SH DESCRIPTION
- X.I chfn
- Xallows the user to change her real name, as printed by
- X.I finger(1)
- Xand
- X.I who(1).
- XIf no
- X.B user
- Xargument is given, the real name is changed for the person
- Xcurrently logged in.
- X.PP
- XIf no
- X.B realname
- Xis given, the current name is printed, and a new one is asked.
- X.PP
- XDepending on choices made by the system administrator, it might
- Xor might not be possible to modify someone else's name. The program
- Xwill then ask for the correct password first.
- X.SH SEE ALSO
- Xchsh(1), finger(1), who(1)
- X.SH DIAGNOSTICS
- XAll kinds of problems with the password file, and locking it,
- Xare reported, and the program exits.
- X.SH AUTHOR
- XK. Richard Magill, rich@rexaco1.UUCP
- X.br
- XExtensively modified by Jack Jansen, jack@htsa.UUCP.
- END_OF_FILE
- if test 829 -ne `wc -c <'chfn.1'`; then
- echo shar: \"'chfn.1'\" unpacked with wrong size!
- fi
- # end of 'chfn.1'
- fi
- if test -f 'chsh.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'chsh.1'\"
- else
- echo shar: Extracting \"'chsh.1'\" \(982 characters\)
- sed "s/^X//" >'chsh.1' <<'END_OF_FILE'
- X.TH CHSH 1 Local
- X.SH NAME
- Xchsh \- change login shell
- X.SH SYNOPSIS
- X.B chsh
- X[ user [ shell ] ]
- X.SH DESCRIPTION
- X.I chsh
- Xallows the user to change her login shell.
- XIf no
- X.B user
- Xargument is given, the login shell is changed for the person
- Xcurrently logged in.
- X.PP
- XIf no
- X.B shell
- Xis given, the current shell is printed, and a new one is asked.
- X.PP
- XDepending on choices made by the system administrator, it might
- Xor might not be possible to modify someone else's shell. The program
- Xwill then ask for the correct password first.
- X.SH SEE ALSO
- Xchfn(1), login(1)
- X.SH DIAGNOSTICS
- XThe
- X.B shell
- Xgiven is checked for existence, and executability.
- X.br
- XAlso, all kinds of problems with the password file, and locking it,
- Xare reported, and the program exits.
- X.SH BUGS
- XThe executability check only looks at the mode, so it doesn't
- Xguarantee that you will be able to log in with the given shell.
- X.SH AUTHOR
- XK. Richard Magill, rich@rexaco1.UUCP
- X.br
- XExtensively modified by Jack Jansen, jack@htsa.UUCP.
- END_OF_FILE
- if test 982 -ne `wc -c <'chsh.1'`; then
- echo shar: \"'chsh.1'\" unpacked with wrong size!
- fi
- # end of 'chsh.1'
- fi
- if test -f 'chsh.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'chsh.c'\"
- else
- echo shar: Extracting \"'chsh.c'\" \(5904 characters\)
- sed "s/^X//" >'chsh.c' <<'END_OF_FILE'
- X/*
- X * This program was originally written by K. Richard Magill,
- X * and posted to mod.sources. It has been extensively
- X * modified by Jack Jansen. See below for details.
- X *
- X * K. Richard Magill, 26-jan-86.
- X * Last Mod 26-jan-86, rich.
- X * Modified by Jack Jansen, 30-jan-86:
- X * - It now runs under V7.
- X * - It now uses (what I believe to be) standard
- X * password file locking and backups.
- X * - Check the size of the new passwd file, abort if
- X * it looks funny.
- X * - Check that there are no :colons: or \nnewlines\n in the
- X * given string.
- X * - Use name from getlogin() if not given, and ask for
- X * parameters if not given.
- X * - if SECURE is defined, don't let other people
- X * muck finger/shell info.
- X */
- X/*#define NOPUTPWENT 1 Define this if you don't have putpwent */
- X#define SECURE 1 /* Only owner/root can change stuff */
- X#define DEBUG 1 /* ALWAYS DEFINE THIS AT FIRST */
- X/*#define void int If your compiler doesn't know void */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <pwd.h>
- X
- X#define WATCH(s,x) if(x){perror(s);return(-1);}
- X
- Xchar *PASSWD = "/etc/passwd";
- X#ifndef DEBUG
- Xchar *BACKUP = "/etc/passwd.bak";
- Xchar *LOCK = "/etc/vipw.lock";
- Xchar *TEMP = "/etc/ptmp";
- Xchar *BAD_TEMP = "/etc/ptmp.bad";
- X#else
- Xchar *LOCK = "vipw.lock";
- Xchar *TEMP = "ptmp";
- Xchar *BAD_TEMP = "ptmp.bad";
- X#endif DEBUG
- Xchar ArgBuf[128];
- Xchar *Arg = ArgBuf;
- X
- Xvoid endpwent(), perror();
- Xchar *crypt(), *getpass(), *mktemp();
- Xstruct passwd *getpwent(), *getpwnam(), *fgetpwent();
- Xchar *index();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X register int i;
- X register struct passwd *p;
- X FILE *fout;
- X int target_id; /* Who are we changing? */
- X struct stat stat_buf;
- X long OldLen, NewLen; /* Old/New length of passwd */
- X long LenDiff; /* Expected length dif. */
- X int ShellMode; /* True if chsh */
- X char *UserName; /* Who are we working for */
- X
- X if( strcmp(argv[0], "chsh") == 0 ) ShellMode = 1; else
- X if( strcmp(argv[0], "chfn") != 0 ) {
- X fprintf(stderr,"Sorry, program name should be 'chsh' or 'chfn'.\n");
- X exit(1);
- X }
- X
- X if( argc >= 2 ) { /* Login name given */
- X UserName = argv[1];
- X } else {
- X UserName = getlogin();
- X printf("Changing %s for %s\n", ShellMode ? "login shell":
- X "real name", UserName);
- X }
- X
- X /* is this person real? */
- X
- X if ((p = getpwnam(UserName)) == NULL) {
- X (void) fprintf(stderr, "%s: don't know %s\n",
- X argv[0], UserName);
- X return(-1);
- X } /* if person isn't real */
- X
- X /* do we have permission to do this? */
- X target_id = p->pw_uid;
- X
- X if ((i = getuid()) != 0 && i != target_id) {
- X#ifdef SECURE
- X fprintf(stderr,"Sorry, you don't have permission to do that.\n");
- X exit(1);
- X#else
- X char salt[3];
- X
- X salt[0] = p->pw_passwd[0];
- X salt[1] = p->pw_passwd[1];
- X salt[3] = '\0';
- X
- X if (*p->pw_passwd != '\0'
- X && strncmp(crypt(getpass("Password: "), salt),
- X p->pw_passwd, 8)) {
- X (void) fprintf(stderr, "Sorry.\n");
- X return(-1);
- X } /* passwd didn't match */
- X#endif SECURE
- X } /* check for permission */
- X
- X /* If in verbose mode, print old info */
- X if( argc <= 2 ) {
- X if( ShellMode ) {
- X printf("Old shell: %s\n", p->pw_shell?p->pw_shell:"");
- X printf("New shell: ");
- X gets(Arg);
- X } else {
- X printf("Old name: %s\n", p->pw_gecos?p->pw_gecos:"");
- X printf("New name: ");
- X gets(Arg);
- X }
- X } else {
- X Arg = argv[2];
- X }
- X
- X /* Check for dirty characters */
- X if( index(Arg, '\n') || index(Arg, ':') ) {
- X fprintf(stderr,"%s: Dirty characters in argument.\n",argv[0]);
- X exit(1);
- X }
- X
- X /* Check that the shell sounds reasonable */
- X if( ShellMode ) {
- X if( *Arg != '/' ) {
- X fprintf(stderr,"%s: shell name should be full path.\n",Arg);
- X exit(1);
- X }
- X WATCH(Arg,stat(Arg,&stat_buf));
- X if( (stat_buf.st_mode & 0111) == 0 ) {
- X fprintf(stderr,"%s is not an executable.\n");
- X exit(1);
- X }
- X }
- X
- X /* set up files */
- X
- X endpwent(); /* close passwd file */
- X
- X setpwent();
- X
- X /* Now, lock the password file */
- X creat(LOCK,0600); /* This might fail. No problem */
- X if( link(LOCK,TEMP) < 0 ) {
- X fprintf(stderr,"Sorry, password file busy.\n");
- X exit(1);
- X }
- X WATCH(TEMP,(fout = fopen(TEMP, "w")) == NULL);
- X
- X while ((p = getpwent()) != NULL) {
- X if (p->pw_uid == target_id) {
- X if (!ShellMode ) {
- X LenDiff = strlen(Arg)-strlen(p->pw_gecos);
- X p->pw_gecos = Arg;
- X } else {
- X LenDiff = (-strlen(p->pw_shell));
- X p->pw_shell = Arg == NULL ? "/bin/sh"
- X : Arg;
- X LenDiff += strlen(p->pw_shell);
- X }
- X } /* if this is entry to be changed */
- X
- X WATCH("putpwent",putpwent(p, fout));
- X } /* while not eof (we couldn't recognize an error) */
- X
- X /* close files */
- X endpwent();
- X fclose(fout);
- X
- X /* Check that sizes are as expected */
- X WATCH(TEMP, stat(TEMP, &stat_buf) );
- X NewLen = stat_buf.st_size;
- X WATCH(PASSWD, stat(PASSWD, &stat_buf) );
- X OldLen = stat_buf.st_size;
- X if( OldLen + LenDiff != NewLen ) {
- X fprintf(stderr,"Sorry, password file changed size: %ld, expected %ld.\n", NewLen, OldLen+LenDiff);
- X fprintf(stderr,"Warn your system administrator, please.\n");
- X WATCH(TEMP, link(TEMP,BAD_TEMP));
- X WATCH(TEMP,unlink(TEMP));
- X WATCH(LOCK,unlink(LOCK));
- X exit(1);
- X }
- X
- X#ifndef DEBUG
- X /* remove old backup if it exists */
- X WATCH(BACKUP,!stat(BACKUP, &stat_buf) && unlink(BACKUP));
- X
- X /* make current passwd file backup */
- X WATCH("linking passwd to passwd.bak",link(PASSWD, BACKUP) || unlink(PASSWD));
- X
- X /* make new file passwd */
- X WATCH("linking temp to passwd",link(TEMP, PASSWD) || unlink(TEMP));
- X WATCH("chmod passwd", chmod(PASSWD, 0644));
- X#endif DEBUG
- X
- X /* Remove lock */
- X WATCH(LOCK,unlink(LOCK));
- X
- X#ifdef DEBUG
- X printf("Now, check that %s looks reasonable.\n", TEMP);
- X#endif DEBUG
- X /* must have succeeded */
- X return(0);
- X} /* main */
- X
- X#ifdef NOPUTPWENT
- Xputpwent(ent, fp)
- X FILE *fp;
- X struct passwd *ent;
- X {
- X
- X fprintf(fp,"%s:%s:%d:%d:%s:%s:%s\n", ent->pw_name, ent->pw_passwd,
- X ent->pw_uid, ent->pw_gid, ent->pw_gecos, ent->pw_dir,
- X ent->pw_shell);
- X return(0);
- X}
- X#endif NOPUTPWENT
- END_OF_FILE
- if test 5904 -ne `wc -c <'chsh.c'`; then
- echo shar: \"'chsh.c'\" unpacked with wrong size!
- fi
- # end of 'chsh.c'
- fi
- echo shar: End of shell archive.
- exit 0
- --
- -------------------------------------------------------------------------------
- Merry Christmas!! Happy New Year! | Remember --
- | Christmas Spirit is not
- Tony Facca [fsfacca@avelon.lerc.nasa.gov] | what you drink..
- -------------------------------------------------------------------------------
-