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