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 /* We only issue this warning if not compiled with support for PAM.
200 If we're using PAM, it's not unheard of that normal pwent passwords
201 would be unavailable. */
204 fprintf (stderr, "%s: couldn't get password of \"%s\"\n",
205 blurb(), (user ? user : "(null)"));
206 #endif /* !HAVE_PAM */
213 /* This has to be called before we've changed our effective user ID,
214 because it might need privileges to get at the encrypted passwords.
215 Returns false if we weren't able to get any passwords, and therefore,
216 locking isn't possible. (It will also have written to stderr.)
222 pwent_priv_init (int argc, char **argv, Bool verbose_p)
226 #ifdef HAVE_ENHANCED_PASSWD
227 set_auth_parameters(argc, argv);
228 check_auth_parameters();
229 #endif /* HAVE_DEC_ENHANCED */
232 encrypted_user_passwd = get_encrypted_passwd(u);
233 encrypted_root_passwd = get_encrypted_passwd(ROOT);
236 if (encrypted_user_passwd)
244 pwent_lock_init (int argc, char **argv, Bool verbose_p)
246 if (encrypted_user_passwd)
255 passwds_match_p (const char *cleartext, const char *ciphertext)
257 char *s = 0; /* note that on some systems, crypt() may return null */
259 s = (char *) crypt (cleartext, ciphertext);
260 if (s && !strcmp (s, ciphertext))
264 /* There seems to be no way to tell at runtime if an HP machine is in
265 "trusted" mode, and thereby, which of crypt() or bigcrypt() we should
266 be calling to compare passwords. So call them both, and see which
269 s = (char *) bigcrypt (cleartext, ciphertext);
270 if (s && !strcmp (s, ciphertext))
273 #endif /* HAVE_BIGCRYPT */
280 /* This can be called at any time, and says whether the typed password
281 belongs to either the logged in user (real uid, not effective); or
285 pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
287 if (encrypted_user_passwd &&
288 passwds_match_p (typed_passwd, encrypted_user_passwd))
291 /* do not allow root to have a null password. */
292 else if (typed_passwd[0] &&
293 encrypted_root_passwd &&
294 passwds_match_p (typed_passwd, encrypted_root_passwd))
302 Bool pwent_lock_init (int argc, char **argv, Bool verbose_p) { return True; }
305 #endif /* NO_LOCKING -- whole file */