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