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"
108 Bool pwent_priv_init (int argc, char **argv, Bool verbose_p);
109 Bool pwent_lock_init (int argc, char **argv, Bool verbose_p);
110 Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
119 /* I think that just checking $USER here is not the best idea. */
123 /* It has been reported that getlogin() returns the wrong user id on some
124 very old SGI systems... And I've seen it return the string "rlogin"
125 sometimes! Screw it, using getpwuid() should be enough...
127 /* u = (char *) getlogin ();
130 /* getlogin() fails if not attached to a terminal; in that case, use
131 getpwuid(). (Note that in this case, we're not doing shadow stuff, since
132 all we're interested in is the name, not the password. So that should
133 still work. Right?) */
136 struct passwd *p = getpwuid (getuid ());
137 u = (p ? p->pw_name : 0);
140 return (u ? strdup(u) : 0);
148 char *u = getenv("USER");
149 return (u ? strdup(u) : 0);
156 passwd_known_p (const char *pw)
159 pw[0] != '*' && /* This would be sensible... */
160 strlen(pw) > 4); /* ...but this is what Solaris does. */
165 get_encrypted_passwd(const char *user)
170 if (user && *user && !result)
171 { /* First check the shadow passwords. */
172 PWTYPE p = GETPW((char *) user);
173 if (p && passwd_known_p (p->PWPSLOT))
174 result = strdup(p->PWPSLOT);
178 if (user && *user && !result)
179 { /* Check non-shadow passwords too. */
180 struct passwd *p = getpwnam(user);
181 if (p && passwd_known_p (p->pw_passwd))
182 result = strdup(p->pw_passwd);
185 /* The manual for passwd(4) on HPUX 10.10 says:
187 Password aging is put in effect for a particular user if his
188 encrypted password in the password file is followed by a comma and
189 a nonnull string of characters from the above alphabet. This
190 string defines the "age" needed to implement password aging.
192 So this means that passwd->pw_passwd isn't simply a string of cyphertext,
193 it might have trailing junk. So, if there is a comma in the string, and
194 that comma is beyond position 13, terminate the string before the comma.
196 if (result && strlen(result) > 13)
198 char *s = strchr (result+13, ',');
204 /* We only issue this warning if not compiled with support for PAM.
205 If we're using PAM, it's not unheard of that normal pwent passwords
206 would be unavailable. */
209 fprintf (stderr, "%s: couldn't get password of \"%s\"\n",
210 blurb(), (user ? user : "(null)"));
211 #endif /* !HAVE_PAM */
218 /* This has to be called before we've changed our effective user ID,
219 because it might need privileges to get at the encrypted passwords.
220 Returns false if we weren't able to get any passwords, and therefore,
221 locking isn't possible. (It will also have written to stderr.)
227 pwent_priv_init (int argc, char **argv, Bool verbose_p)
231 #ifdef HAVE_ENHANCED_PASSWD
232 set_auth_parameters(argc, argv);
233 check_auth_parameters();
234 #endif /* HAVE_DEC_ENHANCED */
237 encrypted_user_passwd = get_encrypted_passwd(u);
238 encrypted_root_passwd = get_encrypted_passwd(ROOT);
241 if (encrypted_user_passwd)
249 pwent_lock_init (int argc, char **argv, Bool verbose_p)
251 if (encrypted_user_passwd)
260 passwds_match_p (const char *cleartext, const char *ciphertext)
262 char *s = 0; /* note that on some systems, crypt() may return null */
264 s = (char *) crypt (cleartext, ciphertext);
265 if (s && !strcmp (s, ciphertext))
269 /* There seems to be no way to tell at runtime if an HP machine is in
270 "trusted" mode, and thereby, which of crypt() or bigcrypt() we should
271 be calling to compare passwords. So call them both, and see which
274 s = (char *) bigcrypt (cleartext, ciphertext);
275 if (s && !strcmp (s, ciphertext))
278 #endif /* HAVE_BIGCRYPT */
285 /* This can be called at any time, and says whether the typed password
286 belongs to either the logged in user (real uid, not effective); or
290 pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
292 if (encrypted_user_passwd &&
293 passwds_match_p (typed_passwd, encrypted_user_passwd))
296 #ifdef ALLOW_ROOT_PASSWD
297 /* do not allow root to have a null password. */
298 else if (typed_passwd[0] &&
299 encrypted_root_passwd &&
300 passwds_match_p (typed_passwd, encrypted_root_passwd))
302 #endif /* ALLOW_ROOT_PASSWD */
309 Bool pwent_lock_init (int argc, char **argv, Bool verbose_p) { return True; }
312 #endif /* NO_LOCKING -- whole file */