1 /* passwd-pwent.c --- verifying typed passwords with the OS.
2 * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
17 #ifndef NO_LOCKING /* whole file */
30 #include <sys/types.h>
40 # include <sys/param.h>
41 # if _BSDI_VERSION >= 199608
47 #if defined(HAVE_SHADOW_PASSWD) /* passwds live in /etc/shadow */
50 # define PWTYPE struct spwd *
51 # define PWPSLOT sp_pwdp
52 # define GETPW getspnam
54 #elif defined(HAVE_ENHANCED_PASSWD) /* passwds live in /tcb/files/auth/ */
55 /* M.Matsumoto <matsu@yao.sharp.co.jp> */
56 # include <sys/security.h>
59 # define PWTYPE struct pr_passwd *
60 # define PWPSLOT ufld.fd_encrypt
61 # define GETPW getprpwnam
63 #elif defined(HAVE_ADJUNCT_PASSWD)
65 # include <sys/label.h>
66 # include <sys/audit.h>
69 # define PWTYPE struct passwd_adjunct *
70 # define PWPSLOT pwa_passwd
71 # define GETPW getpwanam
73 #elif defined(HAVE_HPUX_PASSWD)
75 # include <hpsecurity.h>
78 # define PWTYPE struct s_passwd *
79 # define PWPSLOT pw_passwd
80 # define GETPW getspwnam
82 # define HAVE_BIGCRYPT
96 extern const char *blurb(void);
98 static char *encrypted_root_passwd = 0;
99 static char *encrypted_user_passwd = 0;
102 # define ROOT "SYSTEM"
114 /* I think that just checking $USER here is not the best idea. */
118 /* It has been reported that getlogin() returns the wrong user id on some
119 very old SGI systems... And I've seen it return the string "rlogin"
120 sometimes! Screw it, using getpwuid() should be enough...
122 /* u = (char *) getlogin ();
125 /* getlogin() fails if not attached to a terminal; in that case, use
126 getpwuid(). (Note that in this case, we're not doing shadow stuff, since
127 all we're interested in is the name, not the password. So that should
128 still work. Right?) */
131 struct passwd *p = getpwuid (getuid ());
132 u = (p ? p->pw_name : 0);
135 return (u ? strdup(u) : 0);
143 char *u = getenv("USER");
144 return (u ? strdup(u) : 0);
151 passwd_known_p (const char *pw)
154 pw[0] != '*' && /* This would be sensible... */
155 strlen(pw) > 4); /* ...but this is what Solaris does. */
160 get_encrypted_passwd(const char *user)
165 if (user && *user && !result)
166 { /* First check the shadow passwords. */
167 PWTYPE p = GETPW((char *) user);
168 if (p && passwd_known_p (p->PWPSLOT))
169 result = strdup(p->PWPSLOT);
173 if (user && *user && !result)
174 { /* Check non-shadow passwords too. */
175 struct passwd *p = getpwnam(user);
176 if (p && passwd_known_p (p->pw_passwd))
177 result = strdup(p->pw_passwd);
180 /* The manual for passwd(4) on HPUX 10.10 says:
182 Password aging is put in effect for a particular user if his
183 encrypted password in the password file is followed by a comma and
184 a nonnull string of characters from the above alphabet. This
185 string defines the "age" needed to implement password aging.
187 So this means that passwd->pw_passwd isn't simply a string of cyphertext,
188 it might have trailing junk. So, if there is a comma in the string, and
189 that comma is beyond position 13, terminate the string before the comma.
191 if (result && strlen(result) > 13)
193 char *s = strchr (result+13, ',');
199 fprintf (stderr, "%s: couldn't get password of \"%s\"\n",
200 blurb(), (user ? user : "(null)"));
207 /* This has to be called before we've changed our effective user ID,
208 because it might need privileges to get at the encrypted passwords.
209 Returns false if we weren't able to get any passwords, and therefore,
210 locking isn't possible. (It will also have written to stderr.)
216 pwent_lock_init (int argc, char **argv, Bool verbose_p)
220 #ifdef HAVE_ENHANCED_PASSWD
221 set_auth_parameters(argc, argv);
222 check_auth_parameters();
223 #endif /* HAVE_DEC_ENHANCED */
226 encrypted_user_passwd = get_encrypted_passwd(u);
227 encrypted_root_passwd = get_encrypted_passwd(ROOT);
230 if (encrypted_user_passwd)
238 passwds_match_p (const char *cleartext, const char *ciphertext)
240 char *s = 0; /* note that on some systems, crypt() may return null */
242 s = (char *) crypt (cleartext, ciphertext);
243 if (s && !strcmp (s, ciphertext))
247 /* There seems to be no way to tell at runtime if an HP machine is in
248 "trusted" mode, and thereby, which of crypt() or bigcrypt() we should
249 be calling to compare passwords. So call them both, and see which
252 s = (char *) bigcrypt (cleartext, ciphertext);
253 if (s && !strcmp (s, ciphertext))
256 #endif /* HAVE_BIGCRYPT */
263 /* This can be called at any time, and says whether the typed password
264 belongs to either the logged in user (real uid, not effective); or
268 pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
270 if (encrypted_user_passwd &&
271 passwds_match_p (typed_passwd, encrypted_user_passwd))
274 /* do not allow root to have a null password. */
275 else if (typed_passwd[0] &&
276 encrypted_root_passwd &&
277 passwds_match_p (typed_passwd, encrypted_root_passwd))
285 Bool pwent_lock_init (int argc, char **argv, Bool verbose_p) { return True; }
288 #endif /* NO_LOCKING -- whole file */