http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[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 Bool lock_priv_init (int argc, char **argv, Bool verbose_p);
67 Bool lock_init (int argc, char **argv, Bool verbose_p);
68 Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p);
69
70 /* The authorization methods to try, in order.
71    Note that the last one (the pwent version) is actually two auth methods,
72    since that code tries shadow passwords, and then non-shadow passwords.
73    (It's all in the same file since the APIs are randomly nearly-identical.)
74  */
75 struct auth_methods methods[] = {
76 # ifdef HAVE_KERBEROS
77   { "Kerberos",         kerberos_lock_init, 0, kerberos_passwd_valid_p,
78                         False, False },
79 # endif
80 # ifdef HAVE_PAM
81   { "PAM",              0, pam_priv_init, pam_passwd_valid_p, 
82                         False, False },
83 # endif
84 # ifdef PASSWD_HELPER_PROGRAM
85   { "external",         0, ext_priv_init, ext_passwd_valid_p,
86                         False, False },
87 #endif
88   { "normal",           pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p,
89                         False, False }
90 };
91
92
93 Bool
94 lock_priv_init (int argc, char **argv, Bool verbose_p)
95 {
96   int i;
97   Bool any_ok = False;
98   for (i = 0; i < countof(methods); i++)
99     {
100       if (!methods[i].priv_init)
101         methods[i].priv_initted_p = True;
102       else
103         methods[i].priv_initted_p = methods[i].priv_init (argc, argv,
104                                                           verbose_p);
105
106       if (methods[i].priv_initted_p)
107         any_ok = True;
108       else if (verbose_p)
109         fprintf (stderr, "%s: initialization of %s passwords failed.\n",
110                  blurb(), methods[i].name);
111     }
112   return any_ok;
113 }
114
115
116 Bool
117 lock_init (int argc, char **argv, Bool verbose_p)
118 {
119   int i;
120   Bool any_ok = False;
121   for (i = 0; i < countof(methods); i++)
122     {
123       if (!methods[i].priv_initted_p)   /* Bail if lock_priv_init failed. */
124         continue;
125
126       if (!methods[i].init)
127         methods[i].initted_p = True;
128       else
129         methods[i].initted_p = methods[i].init (argc, argv, verbose_p);
130
131       if (methods[i].initted_p)
132         any_ok = True;
133       else if (verbose_p)
134         fprintf (stderr, "%s: initialization of %s passwords failed.\n",
135                  blurb(), methods[i].name);
136     }
137   return any_ok;
138 }
139
140
141 Bool 
142 passwd_valid_p (const char *typed_passwd, Bool verbose_p)
143 {
144   int i, j;
145   for (i = 0; i < countof(methods); i++)
146     {
147       int ok_p = (methods[i].initted_p &&
148                   methods[i].valid_p (typed_passwd, verbose_p));
149
150       check_for_leaks (methods[i].name);
151
152       if (ok_p)
153         {
154           /* If we successfully authenticated by method N, but attempting
155              to authenticate by method N-1 failed, mention that (since if
156              an earlier authentication method fails and a later one succeeds,
157              something screwy is probably going on.)
158            */
159           if (verbose_p && i > 0)
160             {
161               for (j = 0; j < i; j++)
162                 if (methods[j].initted_p)
163                   fprintf (stderr,
164                            "%s: authentication via %s passwords failed.\n",
165                            blurb(), methods[j].name);
166               fprintf (stderr,
167                        "%s: authentication via %s passwords succeeded.\n",
168                        blurb(), methods[i].name);
169             }
170
171           return True;          /* Successfully authenticated! */
172         }
173     }
174
175   return False;                 /* Authentication failure. */
176 }
177
178 #endif /* NO_LOCKING -- whole file */