b0a4b8ad10d8af638aa9a800cd3cf86ed4527c20
[xscreensaver] / driver / passwd.c
1 /* passwd.c --- verifying typed passwords with the OS.
2  * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@netscape.com>
3  *
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 
10  * implied warranty.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #ifndef NO_LOCKING  /* whole file */
18
19 #include <stdlib.h>
20 #ifdef HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #ifndef VMS
28 # include <pwd.h>
29 #else /* VMS */
30 # include "vms-pwd.h"
31 #endif /* VMS */
32
33
34 #ifdef __bsdi__
35 # include <sys/param.h>
36 # if _BSDI_VERSION >= 199608
37 #  define BSD_AUTH
38 # endif
39 #endif /* __bsdi__ */
40
41
42 #if defined(HAVE_SHADOW_PASSWD)       /* passwds live in /etc/shadow */
43
44 #   include <shadow.h>
45 #   define PWTYPE   struct spwd *
46 #   define PWPSLOT  sp_pwdp
47 #   define GETPW    getspnam
48
49 #elif defined(HAVE_ENHANCED_PASSWD)      /* passwds live in /tcb/files/auth/ */
50                                       /* M.Matsumoto <matsu@yao.sharp.co.jp> */
51 #   include <sys/security.h>
52 #   include <prot.h>
53
54 #   define PWTYPE   struct pr_passwd *
55 #   define PWPSLOT  ufld.fd_encrypt
56 #   define GETPW    getprpwnam
57
58 #elif defined(HAVE_ADJUNCT_PASSWD)
59
60 #   include <sys/label.h>
61 #   include <sys/audit.h>
62 #   include <pwdadj.h>
63
64 #   define PWTYPE   struct passwd_adjunct *
65 #   define PWPSLOT  pwa_passwd
66 #   define GETPW    getpwanam
67
68 #elif defined(HAVE_HPUX_PASSWD)
69
70 #   include <hpsecurity.h>
71 #   include <prot.h>
72
73 #   define PWTYPE   struct s_passwd *
74 #   define PWPSLOT  pw_passwd
75 #   define GETPW    getspwnam
76 #   define crypt    bigcrypt
77
78 #endif
79
80
81 /* blargh */
82 #undef  Bool
83 #undef  True
84 #undef  False
85 #define Bool  int
86 #define True  1
87 #define False 0
88
89
90 extern char *progname;
91
92 static char *encrypted_root_passwd = 0;
93 static char *encrypted_user_passwd = 0;
94
95 #ifdef VMS
96 # define ROOT "SYSTEM"
97 #else
98 # define ROOT "root"
99 #endif
100
101
102
103 #ifndef VMS
104
105 static char *
106 user_name (void)
107 {
108   /* I think that just checking $USER here is not the best idea. */
109
110   const char *u = 0;
111
112   /* It has been reported that getlogin() returns the wrong user id on some
113      very old SGI systems...  And I've seen it return the string "rlogin"
114      sometimes!  Screw it, using getpwuid() should be enough...
115    */
116 /* u = (char *) getlogin ();
117  */
118
119   /* getlogin() fails if not attached to a terminal; in that case, use
120      getpwuid().  (Note that in this case, we're not doing shadow stuff, since
121      all we're interested in is the name, not the password.  So that should
122      still work.  Right?) */
123   if (!u || !*u)
124     {
125       struct passwd *p = getpwuid (getuid ());
126       u = (p ? p->pw_name : 0);
127     }
128
129   return (u ? strdup(u) : 0);
130 }
131
132 #else  /* VMS */
133
134 static char *
135 user_name (void)
136 {
137   char *u = getenv("USER");
138   return (u ? strdup(u) : 0);
139 }
140
141 #endif /* VMS */
142
143
144 static Bool
145 passwd_known_p (const char *pw)
146 {
147   return (pw &&
148           pw[0] != '*' &&       /* This would be sensible...         */
149           strlen(pw) > 4);      /* ...but this is what Solaris does. */
150 }
151
152
153 static char *
154 get_encrypted_passwd(const char *user)
155 {
156   if (user && *user)
157     {
158 #ifdef PWTYPE
159       {                                 /* First check the shadow passwords. */
160         PWTYPE p = GETPW((char *) user);
161         if (p && passwd_known_p (p->PWPSLOT))
162           return strdup(p->PWPSLOT);
163       }
164 #endif
165       {                                 /* Check non-shadow passwords too. */
166         struct passwd *p = getpwnam(user);
167         if (p && passwd_known_p (p->pw_passwd))
168           return strdup(p->pw_passwd);
169       }
170     }
171
172   fprintf (stderr, "%s: couldn't get password of \"%s\"\n",
173            progname, (user ? user : "(null)"));
174
175   return 0;
176 }
177
178
179
180 /* This has to be called before we've changed our effective user ID,
181    because it might need priveleges to get at the encrypted passwords.
182    Returns false if we weren't able to get any passwords, and therefore,
183    locking isn't possible.  (It will also have written to stderr.)
184  */
185
186 #ifndef VMS
187
188 Bool
189 lock_init (int argc, char **argv)
190 {
191   char *u;
192
193 #ifdef HAVE_ENHANCED_PASSWD
194   set_auth_parameters(argc, argv);
195   check_auth_parameters();
196 #endif /* HAVE_DEC_ENHANCED */
197
198   u = user_name();
199   encrypted_user_passwd = get_encrypted_passwd(u);
200   encrypted_root_passwd = get_encrypted_passwd(ROOT);
201   if (u) free (u);
202
203   if (encrypted_user_passwd)
204     return True;
205   else
206     return False;
207 }
208
209
210 /* This can be called at any time, and says whether the typed password
211    belongs to either the logged in user (real uid, not effective); or
212    to root.
213  */
214 Bool
215 passwd_valid_p (const char *typed_passwd)
216 {
217   char *s = 0;  /* note that on some systems, crypt() may return null */
218
219   if (encrypted_user_passwd &&
220       (s = (char *) crypt (typed_passwd, encrypted_user_passwd)) &&
221       !strcmp (s, encrypted_user_passwd))
222     return True;
223
224   /* do not allow root to have a null password. */
225   else if (typed_passwd[0] &&
226            encrypted_root_passwd &&
227            (s = (char *) crypt (typed_passwd, encrypted_root_passwd)) &&
228            !strcmp (s, encrypted_root_passwd))
229     return True;
230
231   else
232     return False;
233 }
234
235 #else  /* VMS */
236 Bool lock_init (int argc, char **argv) { return True; }
237 #endif /* VMS */
238
239
240 #endif /* NO_LOCKING -- whole file */