drears@ardec.arpa (Dennis G. Rears (FSAC)) (12/27/88)
This happens on a VAX 8600 running ULTRIK but does not happen on Goulds or Pyramids. I have a lock program I wrote several years ago. When I run it on top of /usr/ucb/script I get a Bus Error when I type in my password. Any idea why? Here is the program lock: #include <stdio.h> #include <pwd.h> #include <signal.h> /* lock.c Author 1LT Dennis Rears 724-2474 <drears@ardc> This program locks the terminal until that person's password is typed in. This is in place of the system lock program. This must be compiled using the berekly universe. */ main() { struct passwd *pwd, *getpwent(); char *strcpy(); char *getpass(), *getlogin(), *uname, *oldpass, *pass, *crypt(); int endpwent(), tries = 0, wrong; (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTSTP, SIG_IGN); /* This gets the password entry from the file */ uname = getlogin(); /* What happens if the UTMP file is screwed? */ while ((pwd = getpwent()) != NULL && strcmp (pwd->pw_name, uname) != 0) ; (void)endpwent(); /* This checks the response */ wrong = 1; while (wrong) { (void)printf("Enter Password"); (void)fflush(stdout); oldpass = getpass(""); pass = crypt(oldpass, pwd->pw_passwd); if (strcmp(pass, pwd->pw_passwd) == 0) wrong = 0; tries++; } if (tries > 1) (void)printf("There were %d tries at unlocking your terminal\n", tries); } Dennis -------------------------------------------------------------------------- Dennis G. Rears ARPA: drears@ardec-ac4.arpa UUCP: ...!uunet!ardec-ac4.arpa!drears AT&T: 201-724-6639 USPS: Box 210, Wharton, NJ 07885 Work: SMCAR-FSS-E, Bldg 94, Picatinny Ars, NJ 07806 --------------------------------------------------------------------------
debra@alice.UUCP (Paul De Bra) (12/28/88)
In article <17972@adm.BRL.MIL> drears@ardec.arpa (Dennis G. Rears (FSAC)) writes: > This happens on a VAX 8600 running ULTRIK but does not happen on >Goulds or Pyramids. I have a lock program I wrote several years >ago. When I run it on top of /usr/ucb/script I get a Bus Error when I >type in my password. Any idea why? Here is the program lock: >... > uname = getlogin(); /* What happens if the UTMP file is screwed? */ You might want to check on this. script may confuse getlogin. The 4.3 manual says: If getlogin is called within a process that is not attached to a terminal, or if there is no entry in /etc/utmp for the process's terminal, getlogin returns a NULL pointer (0). The manual further suggests: A reasonable procedure for determining the login name is to first call getlogin and if it fails, to call getpwuid(getuid()). > oldpass = getpass(""); script may or may not let you turn on/off the echo... after all the standard output of the program goes to script, not to the terminal... (I may be wrong on this one, my unix doesn't have script) One last comment: I would replace the strcmp calls by strncmp. You never know when you will get a bogus Unix version that forgets to 0-terminate a name from utmp or passwd when it is 8 characters long. Paul. -- ------------------------------------------------------ |debra@research.att.com | uunet!research!debra | ------------------------------------------------------
drears@ardec.arpa (Dennis G. Rears (FSAC)) (12/31/88)
I like to thank everyone who responded to this. The problem was that getlogin() was returning NULL and I wasn't checking for it. When script runs it open /dev/ptyX as a tty which of course isn't in utmp. I have taken the advice to use it based upon uid. Dennis
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/02/89)
In article <17972@adm.BRL.MIL> drears@ardec.arpa (Dennis G. Rears (FSAC)) writes: > This happens on a VAX 8600 running ULTRIK but does not happen on >Goulds or Pyramids. I have a lock program I wrote several years >ago. When I run it on top of /usr/ucb/script I get a Bus Error when I >type in my password. Any idea why? ... getlogin() can, and probably does when run under "script", return NULL. You didn't test for this and so you tried to strcmp() with the second argument NULL. strcmp() trusted you and you let it down..
sme@computing-maths.cardiff.ac.uk (Simon Elliott) (01/09/89)
Getlogin returns a pointer to the login name as found in /etc/utmp. /etc/utmp contains a record for each terminal on the system (including pseudo-terminals (ttyp?). The login name part is blank or null until login fills it it. When you run script, your controlling terminal is a pseudo-terminal (eg. /dev/ttyp0). Your login name is not put into /etc/utmp for this pseudo-terminal so the entry is still null. A program run in script is attached to the pseudo terminal so getlogin() returns a pointer to the null string entry from utmp. Getlogin returns the NULL pointer only if it called from a process which is NOT attached to any terminal (even a pseudo one). -------cut here------- #include <stdio.h> #include <pwd.h> main(ac,av) char *av[]; { char *uname, getlogin(); struct passwd *pwd, getpwnam(), getpwuid(); if ((uname = getlogin()) == NULL) { pwd = getpwuid(getuid()); fprintf(stderr, "uid: %d\n", getuid()); } else { pwd = getpwnam(uname); fprintf(stderr, "uname: *(char *)0x%lx = \"%s\"\n", uname, uname); } if (pwd == NULL) { fprintf(stderr, "%s: cannot locate passwd entry!\007\n", av[0]); exit(1); } } ---------cut here------- Try running this a) from shell prompt; b) under 'script' (uses pseudo-tty); c) using 'at' (detaches from terminal). -- -------------------------------------------------------------------------- Simon Elliott Internet: sme%v1.cm.cf.ac.uk@cunyvm.cuny.edu UWCC Computer Centre JANET: sme@uk.ac.cf.cm.v1 40/41 Park Place UUCP: {backbones}!mcvax!ukc!reading!cf-cm!sme Cardiff, Wales PHONE: +44 222 874300
chris@mimsy.UUCP (Chris Torek) (01/11/89)
In article <596@cf-cm.UUCP> sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes: >... A program run in script is attached to [a] pseudo terminal so >getlogin() returns a pointer to the null string entry from utmp. >Getlogin returns the NULL pointer only if it called from a process >which is NOT attached to any terminal (even a pseudo one). Not so. If I may quote from getlogin(): #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getlogin.c 5.3 (Berkeley) 5/9/86"; #endif LIBC_SCCS and not lint ... if (ubuf.ut_name[0] == '\0') return (0); ... return (ubuf.ut_name); I believe *getlogin()==0 may be true under some broken Unixes. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ka@june.cs.washington.edu (Kenneth Almquist) (01/12/89)
chris@mimsy.UUCP (Chris Torek) writes: > sme@computing-maths.cardiff.ac.uk (Simon Elliott) writes: >> ... A program run in script is attached to [a] pseudo terminal so >> getlogin() returns a pointer to the null string entry from utmp. >> Getlogin returns the NULL pointer only if it called from a process >> which is NOT attached to any terminal (even a pseudo one). > > Not so. If I may quote from getlogin(): > > #if defined(LIBC_SCCS) && !defined(lint) > static char sccsid[] = "@(#)getlogin.c 5.3 (Berkeley) 5/9/86"; > #endif LIBC_SCCS and not lint > > ... > if (ubuf.ut_name[0] == '\0') > return (0); > ... > return (ubuf.ut_name); > > I believe *getlogin()==0 may be true under some broken Unixes. The source may be the final reference, but there's no law against looking things up in the manual. If I may quote from the 4.3 BSD manual (dated April 1986): Getlogin returns a pointer to the login name as found in /etc/utmp.... If getlogin is called within a process that is not attached to a terminal or if there is no entry in /etc/utmp for the process's terminal, getlogin returns a NULL pointer (0). A process running under script is attached to a pty, and there is (presumably) a utmp entry for the pty, so getlogin should return the user name from the /etc/utmp entry for the pty. Since no user is actually logged onto the pty, the name in the /etc/utmp entry is the null string. So unless Berkeley screwed up, code that depends upon getlogin returning a NULL pointer when it encounters a null string won't be portable to vanilla 4.3 BSD. It certainly won't be portable to Ultrix 2.3 (a 4.2 BSD derivative which we run here). I will resist commenting on whether 4.2 and 4.3 BSD can accurately be described as "broken Unixes" and simply suggest that testing the results of getlogin against both NULL and "" is good practice. Kenneth Almquist
chris@mimsy.UUCP (Chris Torek) (01/12/89)
In article <6925@june.cs.washington.edu> ka@june.cs.washington.edu (Kenneth Almquist) writes: >The source may be the final reference, but there's no law against looking >things up in the manual. (I like that line; shall have to use it myself someday...) > If getlogin is called within a process that is not attached to > a terminal or if there is no entry in /etc/utmp for the process's > terminal, getlogin returns a NULL pointer (0). The key phrase is `if there is no entry in /etc/utmp'. An entry with utmp.ut_name[0]=='\0' is considered `no entry'. Bad wording in the manual, to say the least. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guy@auspex.UUCP (Guy Harris) (01/13/89)
>A process running under script is attached to a pty, and there is >(presumably) a utmp entry for the pty, so getlogin should return >the user name from the /etc/utmp entry for the pty. Since no user >is actually logged onto the pty, the name in the /etc/utmp entry is >the null string. Which means that the S5R3 and 4.3BSD versions of "getlogin" will return a null pointer. I don't have older versions handy, so I can't say that this behavior dates back to V7. >So unless Berkeley screwed up, code that depends upon getlogin >returning a NULL pointer when it encounters a null string won't be >portable to vanilla 4.3 BSD. Berkeley's only screwup - or AT&T's screwup, if the wording in question is derived from that in the 32V manual page - is that they didn't make it clear that the "utmp" entry in question must not only exist (in the sense that an entry in "/etc/ttys", for V7/BSD, or an entry in "/etc/utmp" of type INIT_PROCES, LOGIN_PROCESS, USER_PROCESS or DEAD_PROCESS, for S5, exists specifying the terminal in question), but that it must represent a valid entry (in the sense that it must not have a null user name). The code in question *is* portable to vanilla 4.3BSD, because 4.3BSD's "getlogin" *does* return a NULL pointer when it encounters a null string; the fact that the manual page may not explicitly say so is arguably a deficiency of the manual page (unless you consider it to be implicit in the description that the "utmp" entry must really specify a user), but it doesn't affect the portability of code.... >It certainly won't be portable to Ultrix 2.3 (a 4.2 BSD derivative >which we run here). This according to the Ultrix documentation, or the Ultrix code (either by inspecting the code or by probing its behavior)? I don't have 4.2BSD source handy to check, but if 4.2BSD returns NULL if the user name is null and Ultrix doesn't, the screwup there is DEC's. >I will resist commenting on whether 4.2 and 4.3 BSD can accurately >be described as "broken Unixes" If a system that returns NULL if the user name is a null string is broken, that means 4.3BSD, 4.3-tahoe, and S5R3 are broken, and other 4.xBSD and S5 systems may be broken as well - perhaps even V7 and S3. If that's the case, I'd be inclined to say the only thing broken about those systems may be the documentation, and say that systems that *don't* provide that behavior are broken.
ka@june.cs.washington.edu (Kenneth Almquist) (01/13/89)
In article <837@auspex.UUCP>, guy@auspex.UUCP (Guy Harris) writes: > This according to the Ultrix documentation, or the Ultrix code (either > by inspecting the code or by probing its behavior)? I don't have 4.2BSD > source handy to check, but if 4.2BSD returns NULL if the user name is > null and Ultrix doesn't, the screwup there is DEC's. It's from the code. The Ultrix manual page for getlogin is identical to the 4.3 BSD manual page. The getlogin code for Dynix (which claims 4.2 BSD compatibility) is identical to the Ultrix code, so I assume that the code in both systems is the 4.2 BSD code. What I mean by saying that Berkeley screwed up is that the code and the documentation were in agreement (even if they were both wrong) and then they changed the code without changing the documentation. >> ...the name in the /etc/utmp entry is the null string. > Which means that the S5R3 and 4.3BSD versions of "getlogin" will return > a null pointer. I don't have older versions handy, so I can't say that > this behavior dates back to V7. Well, as I recall the S5R2 code checks for the null string, but null user strings are rare in System V utmp files because when a user logs out in System V this fact is indicated by changing the ut_type field of the utmp entry to DEAD_PROCESS rather than by changing the user name to the null string. I *think* that the check for the null string predates the conversion to the new utmp format, in which case USG Unix at one time (before it got the name System V and the new utmp format) actually returned NULL if called on a terminal with no one logged on. Does S5R3 just contain this same check for a null string, or does in actually check whether the user has logged out? In any case, getlogin is inherently risky under System V since a user can start up a background process, log out, and allow someone else to log in. At this point getlogin will return the login name of the new user, not the name of user that started the background process. (The vhangup call is supposed to prevent this scenario from occurring under Berkeley UNIX.) If a program really wants to find out who invoked it, it should search the password file for the user's id. The name returned by getlogin can be used to resolve the ambiguity if more than one user has the same user id, but because of the above scenario it's probably safer to use the environment variable LOGNAME to resolve any ambiguity. Of course a malicious user can reset LOGNAME; if you have malicious users that you must distinguish between, the only safe approach is to give them separate user ids. Kenneth Almquist
guy@auspex.UUCP (Guy Harris) (01/14/89)
>The getlogin code for Dynix (which claims 4.2 BSD compatibility) is >identical to the Ultrix code, so I assume that the code in both systems >is the 4.2 BSD code. If that is the case, I'm slightly surprised; unfortunately, I don't have 4.2BSD code handy to check against. >I *think* that the check for the null string predates the conversion to >the new utmp format, In which case it may well date back to V7; if so, I'd be even more surprised if the check were missing from 4.2. >Does S5R3 just contain this same check for a null string, or does >in actually check whether the user has logged out? S5R3's "getlogin" checks whether "ubuf.ut_user[0]" is '\0', and if so returns NULL. It does not check the "ut_type" field of the entry. "ttyslot" accepts either INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. Since DEAD_PROCESS or INIT_PROCESS will show up if somebody's logged out and nobody's logged in subsequently, and since "init" stuffs the name of the *program* it ran into "ut_user" when it sets the type to INIT_PROCESS, this seems to indicate that if there's nobody logged in, "getlogin" will neither return NULL *nor* a null string - it'll return the name of the person who logged in last, or something like "getty"! (It obviously won't return a null string, since it checks for that and returns NULL.) Perhaps there's a reason for this behavior, but given what "getlogin" is supposed to do I don't see why it doesn't accept only USER_PROCESS and maybe LOGIN_PROCESS in the "utmp" slot. >In any case, getlogin is inherently risky under System V since a user >can start up a background process, log out, and allow someone else to >log in. At this point getlogin will return the login name of the new >user, not the name of user that started the background process. (The >vhangup call is supposed to prevent this scenario from occurring under >Berkeley UNIX.) It prevents it because it invalidates any file descriptors the program has that refer to that tty. Of course, if you start up a background process and log out, it's not supposed to have any file descriptors for the tty - otherwise, it can do amusing and possibly unpleasant things to the owner of the current session - and "nohup ... &" will ensure that is the case. If you don't do "nohup", the SIGHUP sent to your tty when your login shell exits should blow away the process in question. (This brings up the general problem of disconnecting remnant processes of a session from the session's tty, which is, I think, being discussed in another thread here.) Of course, none of the above is guaranteed to happen, so it's conceivable that a program could have "getlogin" not fail when run in the background and left behind after the session is terminated. >If a program really wants to find out who invoked it, it should search >the password file for the user's id. The name returned by getlogin can >be used to resolve the ambiguity if more than one user has the same >user id, >Of course a malicious user can reset LOGNAME; if you have malicious users >that you must distinguish between, the only safe approach is to give them >separate user ids. If they're malicious, I'd give them separate user IDs just to keep them from being malicious to each other, unless you know they wouldn't do that.... I seem to remember reading somewhere in a V8 manual that V8 had what, if I remember, was an old PWB idea (dating back to V6, when you had 1-byte user IDs and users *had* to share them) of having the login name stored securely in the U area, with a system call to get and set it. Is this the case?
chris@mimsy.UUCP (Chris Torek) (01/14/89)
>>The getlogin code for Dynix (which claims 4.2 BSD compatibility) is >>identical to the Ultrix code, so I assume that the code in both systems >>is the 4.2 BSD code. In article <844@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes: >If that is the case, I'm slightly surprised; unfortunately, I don't have >4.2BSD code handy to check against. I do. The test is missing. The test was usually unnecessary in 4.1BSD, where *getlogin()==0 would be true only if you had actually logged out. Script did not switch control terminals, so getlogin() would find your real login entry. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris