]> granicus.if.org Git - shadow/blob - lib/pwauth.c
Added the subversion svn:keywords property (Id) for proper identification.
[shadow] / lib / pwauth.c
1 /*
2  * Copyright 1992 - 1994, Julianne Frances Haugh
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <config.h>
31
32 #ifndef USE_PAM
33 #ident "$Id$"
34
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include "prototypes.h"
42 #include "defines.h"
43 #include "pwauth.h"
44 #include "getdef.h"
45 #ifdef SKEY
46 #include <skey.h>
47 #endif
48 #ifdef __linux__                /* standard password prompt by default */
49 static const char *PROMPT = gettext_noop ("Password: ");
50 #else
51 static const char *PROMPT = gettext_noop ("%s's Password: ");
52 #endif
53
54 int wipe_clear_pass = 1;
55 char *clear_pass = NULL;
56
57 /*
58  * pw_auth - perform getpass/crypt authentication
59  *
60  *      pw_auth gets the user's cleartext password and encrypts it
61  *      using the salt in the encrypted password. The results are
62  *      compared.
63  */
64
65 int
66 pw_auth (const char *cipher, const char *user, int reason, const char *input)
67 {
68         char prompt[1024];
69         char *clear = NULL;
70         const char *cp;
71         int retval;
72
73 #ifdef  SKEY
74         int use_skey = 0;
75         char challenge_info[40];
76         struct skey skey;
77 #endif
78
79         /*
80          * There are programs for adding and deleting authentication data.
81          */
82
83         if (reason == PW_ADD || reason == PW_DELETE)
84                 return 0;
85
86         /*
87          * There are even programs for changing the user name ...
88          */
89
90         if (reason == PW_CHANGE && input != (char *) 0)
91                 return 0;
92
93         /*
94          * WARNING:
95          *
96          * When we change a password and we are root, we don't prompt.
97          * This is so root can change any password without having to
98          * know it.  This is a policy decision that might have to be
99          * revisited.
100          */
101
102         if (reason == PW_CHANGE && getuid () == 0)
103                 return 0;
104
105         /*
106          * WARNING:
107          *
108          * When we are logging in a user with no ciphertext password,
109          * we don't prompt for the password or anything.  In reality
110          * the user could just hit <ENTER>, so it doesn't really
111          * matter.
112          */
113
114         if (cipher == (char *) 0 || *cipher == '\0')
115                 return 0;
116
117 #ifdef  SKEY
118         /*
119          * If the user has an S/KEY entry show them the pertinent info
120          * and then we can try validating the created cyphertext and the SKEY.
121          * If there is no SKEY information we default to not using SKEY.
122          */
123
124 # ifdef SKEY_BSD_STYLE
125         /*
126          * Some BSD updates to the S/KEY API adds a fourth parameter; the
127          * sizeof of the challenge info buffer.
128          */
129 #  define skeychallenge(s,u,c) skeychallenge(s,u,c,sizeof(c))
130 # endif
131
132         if (skeychallenge (&skey, user, challenge_info) == 0)
133                 use_skey = 1;
134 #endif
135
136         /*
137          * Prompt for the password as required.  FTPD and REXECD both
138          * get the cleartext password for us.
139          */
140
141         if (reason != PW_FTP && reason != PW_REXEC && !input) {
142                 if (!(cp = getdef_str ("LOGIN_STRING")))
143                         cp = _(PROMPT);
144 #ifdef  SKEY
145                 if (use_skey)
146                         printf ("[%s]\n", challenge_info);
147 #endif
148
149                 snprintf (prompt, sizeof prompt, cp, user);
150                 clear = getpass (prompt);
151                 if (!clear) {
152                         static char c[1];
153
154                         c[0] = '\0';
155                         clear = c;
156                 }
157                 input = clear;
158         }
159
160         /*
161          * Convert the cleartext password into a ciphertext string.
162          * If the two match, the return value will be zero, which is
163          * SUCCESS. Otherwise we see if SKEY is being used and check
164          * the results there as well.
165          */
166
167         retval = strcmp (pw_encrypt (input, cipher), cipher);
168
169 #ifdef  SKEY
170         /*
171          * If (1) The password fails to match, and
172          * (2) The password is empty and
173          * (3) We are using OPIE or S/Key, then
174          * ...Re-prompt, with echo on.
175          * -- AR 8/22/1999
176          */
177         if (retval && !input[0] && (use_skey)) {
178                 clear = getpass (prompt);
179                 if (!clear) {
180                         static char c[1];
181
182                         c[0] = '\0';
183                         clear = c;
184                 }
185                 input = clear;
186         }
187
188         if (retval && use_skey) {
189                 int passcheck = -1;
190
191                 if (skeyverify (&skey, input) == 0)
192                         passcheck = skey.n;
193                 if (passcheck > 0)
194                         retval = 0;
195         }
196 #endif
197
198         /*
199          * Things like RADIUS authentication may need the password -
200          * if the external variable wipe_clear_pass is zero, we will
201          * not wipe it (the caller should wipe clear_pass when it is
202          * no longer needed).  --marekm
203          */
204
205         clear_pass = clear;
206         if (wipe_clear_pass && clear && *clear)
207                 strzero (clear);
208         return retval;
209 }
210 #endif                          /* !USE_PAM */