http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.16.tar.gz
[xscreensaver] / driver / passwd.c
1 /* passwd.c --- verifying typed passwords with the OS.
2  * xscreensaver, Copyright (c) 1993-2004 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 <stdio.h>
20 #include <stdlib.h>
21 #ifdef HAVE_UNISTD_H
22 # include <unistd.h>
23 #endif
24
25 extern char *blurb(void);
26 extern void check_for_leaks (const char *where);
27
28
29 /* blargh */
30 #undef  Bool
31 #undef  True
32 #undef  False
33 #define Bool  int
34 #define True  1
35 #define False 0
36
37 #undef countof
38 #define countof(x) (sizeof((x))/sizeof(*(x)))
39
40 struct auth_methods {
41   const char *name;
42   Bool (*init) (int argc, char **argv, Bool verbose_p);
43   Bool (*priv_init) (int argc, char **argv, Bool verbose_p);
44   Bool (*valid_p) (const char *typed_passwd, Bool verbose_p);
45   Bool initted_p;
46   Bool priv_initted_p;
47 };
48
49
50 #ifdef HAVE_KERBEROS
51 extern Bool kerberos_lock_init (int argc, char **argv, Bool verbose_p);
52 extern Bool kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
53 #endif
54 #ifdef HAVE_PAM
55 extern Bool pam_priv_init (int argc, char **argv, Bool verbose_p);
56 extern Bool pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
57 #endif
58 #ifdef PASSWD_HELPER_PROGRAM
59 extern Bool ext_priv_init (int argc, char **argv, Bool verbose_p);
60 extern Bool ext_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
61 #endif
62 extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p);
63 extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p);
64 extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
65
66
67 /* The authorization methods to try, in order.
68    Note that the last one (the pwent version) is actually two auth methods,
69    since that code tries shadow passwords, and then non-shadow passwords.
70    (It's all in the same file since the APIs are randomly nearly-identical.)
71  */
72 struct auth_methods methods[] = {
73 # ifdef HAVE_KERBEROS
74   { "Kerberos",         kerberos_lock_init, 0, kerberos_passwd_valid_p,
75                         False, False },
76 # endif
77 # ifdef HAVE_PAM
78   { "PAM",              0, pam_priv_init, pam_passwd_valid_p, 
79                         False, False },
80 # endif
81 # ifdef PASSWD_HELPER_PROGRAM
82   { "external",         0, ext_priv_init, ext_passwd_valid_p,
83                         False, False },
84 #endif
85   { "normal",           pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p,
86                         False, False }
87 };
88
89
90 Bool
91 lock_priv_init (int argc, char **argv, Bool verbose_p)
92 {
93   int i;
94   Bool any_ok = False;
95   for (i = 0; i < countof(methods); i++)
96     {
97       if (!methods[i].priv_init)
98         methods[i].priv_initted_p = True;
99       else
100         methods[i].priv_initted_p = methods[i].priv_init (argc, argv,
101                                                           verbose_p);
102
103       if (methods[i].priv_initted_p)
104         any_ok = True;
105       else if (verbose_p)
106         fprintf (stderr, "%s: initialization of %s passwords failed.\n",
107                  blurb(), methods[i].name);
108     }
109   return any_ok;
110 }
111
112
113 Bool
114 lock_init (int argc, char **argv, Bool verbose_p)
115 {
116   int i;
117   Bool any_ok = False;
118   for (i = 0; i < countof(methods); i++)
119     {
120       if (!methods[i].priv_initted_p)   /* Bail if lock_priv_init failed. */
121         continue;
122
123       if (!methods[i].init)
124         methods[i].initted_p = True;
125       else
126         methods[i].initted_p = methods[i].init (argc, argv, verbose_p);
127
128       if (methods[i].initted_p)
129         any_ok = True;
130       else if (verbose_p)
131         fprintf (stderr, "%s: initialization of %s passwords failed.\n",
132                  blurb(), methods[i].name);
133     }
134   return any_ok;
135 }
136
137
138 Bool 
139 passwd_valid_p (const char *typed_passwd, Bool verbose_p)
140 {
141   int i, j;
142   for (i = 0; i < countof(methods); i++)
143     {
144       int ok_p = (methods[i].initted_p &&
145                   methods[i].valid_p (typed_passwd, verbose_p));
146
147       check_for_leaks (methods[i].name);
148
149       if (ok_p)
150         {
151           /* If we successfully authenticated by method N, but attempting
152              to authenticate by method N-1 failed, mention that (since if
153              an earlier authentication method fails and a later one succeeds,
154              something screwy is probably going on.)
155            */
156           if (verbose_p && i > 0)
157             {
158               for (j = 0; j < i; j++)
159                 if (methods[j].initted_p)
160                   fprintf (stderr,
161                            "%s: authentication via %s passwords failed.\n",
162                            blurb(), methods[j].name);
163               fprintf (stderr,
164                        "%s: authentication via %s passwords succeeded.\n",
165                        blurb(), methods[i].name);
166             }
167
168           return True;          /* Successfully authenticated! */
169         }
170     }
171
172   return False;                 /* Authentication failure. */
173 }
174
175 #endif /* NO_LOCKING -- whole file */