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
81 # define crypt bigcrypt
95 extern const char *blurb(void);
97 static char *encrypted_root_passwd = 0;
98 static char *encrypted_user_passwd = 0;
101 # define ROOT "SYSTEM"
113 /* I think that just checking $USER here is not the best idea. */
117 /* It has been reported that getlogin() returns the wrong user id on some
118 very old SGI systems... And I've seen it return the string "rlogin"
119 sometimes! Screw it, using getpwuid() should be enough...
121 /* u = (char *) getlogin ();
124 /* getlogin() fails if not attached to a terminal; in that case, use
125 getpwuid(). (Note that in this case, we're not doing shadow stuff, since
126 all we're interested in is the name, not the password. So that should
127 still work. Right?) */
130 struct passwd *p = getpwuid (getuid ());
131 u = (p ? p->pw_name : 0);
134 return (u ? strdup(u) : 0);
142 char *u = getenv("USER");
143 return (u ? strdup(u) : 0);
150 passwd_known_p (const char *pw)
153 pw[0] != '*' && /* This would be sensible... */
154 strlen(pw) > 4); /* ...but this is what Solaris does. */
159 get_encrypted_passwd(const char *user)
164 if (user && *user && !result)
165 { /* First check the shadow passwords. */
166 PWTYPE p = GETPW((char *) user);
167 if (p && passwd_known_p (p->PWPSLOT))
168 result = strdup(p->PWPSLOT);
172 if (user && *user && !result)
173 { /* Check non-shadow passwords too. */
174 struct passwd *p = getpwnam(user);
175 if (p && passwd_known_p (p->pw_passwd))
176 result = strdup(p->pw_passwd);
179 /* The manual for passwd(4) says:
181 Password aging is put in effect for a particular user if his
182 encrypted password in the password file is followed by a comma and
183 a nonnull string of characters from the above alphabet. This
184 string defines the "age" needed to implement password aging.
186 So this means that passwd->pw_passwd isn't simply a string of cyphertext,
187 it might have trailing junk. So, if there is a comma in the string, and
188 that comma is beyond position 13, terminate the string before the comma.
190 if (result && strlen(result) > 13)
192 char *s = strchr (result+13, ',');
198 fprintf (stderr, "%s: couldn't get password of \"%s\"\n",
199 blurb(), (user ? user : "(null)"));
206 /* This has to be called before we've changed our effective user ID,
207 because it might need privileges to get at the encrypted passwords.
208 Returns false if we weren't able to get any passwords, and therefore,
209 locking isn't possible. (It will also have written to stderr.)
215 pwent_lock_init (int argc, char **argv, Bool verbose_p)
219 #ifdef HAVE_ENHANCED_PASSWD
220 set_auth_parameters(argc, argv);
221 check_auth_parameters();
222 #endif /* HAVE_DEC_ENHANCED */
225 encrypted_user_passwd = get_encrypted_passwd(u);
226 encrypted_root_passwd = get_encrypted_passwd(ROOT);
229 if (encrypted_user_passwd)
236 /* This can be called at any time, and says whether the typed password
237 belongs to either the logged in user (real uid, not effective); or
241 pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
243 char *s = 0; /* note that on some systems, crypt() may return null */
245 if (encrypted_user_passwd &&
246 (s = (char *) crypt (typed_passwd, encrypted_user_passwd)) &&
247 !strcmp (s, encrypted_user_passwd))
250 /* do not allow root to have a null password. */
251 else if (typed_passwd[0] &&
252 encrypted_root_passwd &&
253 (s = (char *) crypt (typed_passwd, encrypted_root_passwd)) &&
254 !strcmp (s, encrypted_root_passwd))
262 Bool pwent_lock_init (int argc, char **argv, Bool verbose_p) { return True; }
265 #endif /* NO_LOCKING -- whole file */