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