]> granicus.if.org Git - linux-pam/blob - libpam/pam_get_authtok.c
Fix grammar of messages printed via pam_prompt
[linux-pam] / libpam / pam_get_authtok.c
1 /*
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that the following conditions
4  * are met:
5  * 1. Redistributions of source code must retain the above copyright
6  *    notice, and the entire permission notice in its entirety,
7  *    including the disclaimer of warranties.
8  * 2. Redistributions in binary form must reproduce the above copyright
9  *    notice, this list of conditions and the following disclaimer in the
10  *    documentation and/or other materials provided with the distribution.
11  * 3. The name of the author may not be used to endorse or promote
12  *    products derived from this software without specific prior
13  *    written permission.
14  *
15  * ALTERNATIVELY, this product may be distributed under the terms of
16  * the GNU Public License, in which case the provisions of the GPL are
17  * required INSTEAD OF the above restrictions.  (This clause is
18  * necessary due to a potential bad interaction between the GPL and
19  * the restrictions contained in a BSD-style copyright.)
20  *
21  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "config.h"
35 #include "pam_private.h"
36
37 #include <security/pam_ext.h>
38
39 #define PROMPT _("Password: ")
40 /* For Translators: "%s%s" could be replaced with "<service> " or "". */
41 #define PROMPTCURRENT _("Current %s%spassword: ")
42 /* For Translators: "%s%s" could be replaced with "<service> " or "". */
43 #define PROMPT1 _("New %s%spassword: ")
44 /* For Translators: "%s%s" could be replaced with "<service> " or "". */
45 #define PROMPT2 _("Retype new %s%spassword: ")
46 #define MISTYPED_PASS _("Sorry, passwords do not match.")
47
48 #define PAM_GETAUTHTOK_NOVERIFY  1
49
50 static const char *
51 get_option (pam_handle_t *pamh, const char *option)
52 {
53   int i;
54   size_t len;
55
56
57   if (option == NULL || pamh == NULL ||
58       pamh->mod_argc == 0 || pamh->mod_argv == NULL)
59     return NULL;
60
61   len = strlen (option);
62
63   for (i = 0; i < pamh->mod_argc; i++)
64     {
65       if (strncmp (option, pamh->mod_argv[i], len) == 0)
66         {
67           if (pamh->mod_argv[i][len] == '=')
68             return &(pamh->mod_argv[i][len+1]);
69           else if (pamh->mod_argv[i][len] == '\0')
70             return "";
71         }
72     }
73   return NULL;
74 }
75
76
77 static int
78 pam_get_authtok_internal (pam_handle_t *pamh, int item,
79                           const char **authtok, const char *prompt,
80                           unsigned int flags)
81
82 {
83   char *resp[2] = {NULL, NULL};
84   const void *prevauthtok;
85   const char *authtok_type = "";
86   int chpass = 0; /* Password change, ask twice for it */
87   int retval;
88
89   if (authtok == NULL)
90     return PAM_SYSTEM_ERR;
91
92   /* PAM_AUTHTOK in password stack returns new password,
93      which needs to be verified. */
94   if (pamh->choice == PAM_CHAUTHTOK)
95     {
96       if (item == PAM_AUTHTOK)
97         {
98           chpass = 1;
99           if (!(flags & PAM_GETAUTHTOK_NOVERIFY))
100             ++chpass;
101         }
102       authtok_type = get_option (pamh, "authtok_type");
103       if (authtok_type == NULL)
104         {
105           retval = pam_get_item (pamh, PAM_AUTHTOK_TYPE, (const void **)&authtok_type);
106           if (retval != PAM_SUCCESS || authtok_type == NULL)
107             authtok_type = "";
108         }
109       else
110         pam_set_item(pamh, PAM_AUTHTOK_TYPE, authtok_type);
111     }
112
113   retval = pam_get_item (pamh, item, &prevauthtok);
114   if (retval == PAM_SUCCESS && prevauthtok != NULL)
115     {
116       *authtok = prevauthtok;
117       return PAM_SUCCESS;
118     }
119   else if (get_option (pamh, "use_first_pass") ||
120            (chpass && get_option (pamh, "use_authtok")))
121     {
122       if (prevauthtok == NULL)
123         {
124           if (chpass)
125             return PAM_AUTHTOK_ERR;
126           else
127             return PAM_AUTH_ERR;
128         }
129       else
130         return retval;
131     }
132
133   if (prompt != NULL)
134     {
135       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0],
136                            "%s", prompt);
137       if (retval == PAM_SUCCESS && chpass > 1 && resp[0] != NULL)
138         retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1],
139                              _("Retype %s"), prompt);
140     }
141   else if (chpass)
142     {
143       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0],
144                            PROMPT1, authtok_type,
145                            strlen (authtok_type) > 0?" ":"");
146       if (retval == PAM_SUCCESS && chpass > 1 && resp[0] != NULL)
147         retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[1],
148                              PROMPT2, authtok_type,
149                              strlen (authtok_type) > 0?" ":"");
150     }
151   else if (item == PAM_OLDAUTHTOK)
152     retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0],
153                          PROMPTCURRENT, authtok_type,
154                          strlen (authtok_type) > 0?" ":"");
155   else
156     retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp[0], "%s",
157                          PROMPT);
158
159   if (retval != PAM_SUCCESS || resp[0] == NULL ||
160       (chpass > 1 && resp[1] == NULL))
161     {
162       /* We want to abort */
163       if (chpass)
164         pam_error (pamh, _("Password change has been aborted."));
165       return PAM_AUTHTOK_ERR;
166     }
167
168   if (chpass > 1 && strcmp (resp[0], resp[1]) != 0)
169     {
170       pam_error (pamh, MISTYPED_PASS);
171       _pam_overwrite (resp[0]);
172       _pam_drop (resp[0]);
173       _pam_overwrite (resp[1]);
174       _pam_drop (resp[1]);
175       return PAM_TRY_AGAIN;
176     }
177
178   _pam_overwrite (resp[1]);
179   _pam_drop (resp[1]);
180
181   retval = pam_set_item (pamh, item, resp[0]);
182   _pam_overwrite (resp[0]);
183   _pam_drop (resp[0]);
184   if (retval != PAM_SUCCESS)
185     return retval;
186
187   return pam_get_item(pamh, item, (const void **)authtok);
188 }
189
190 int
191 pam_get_authtok (pam_handle_t *pamh, int item, const char **authtok,
192                  const char *prompt)
193 {
194   return pam_get_authtok_internal (pamh, item, authtok, prompt, 0);
195 }
196
197
198 int
199 pam_get_authtok_noverify (pam_handle_t *pamh, const char **authtok,
200                           const char *prompt)
201 {
202   return pam_get_authtok_internal (pamh, PAM_AUTHTOK, authtok, prompt,
203                                    PAM_GETAUTHTOK_NOVERIFY);
204 }
205
206 int
207 pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
208                         const char *prompt)
209 {
210   char *resp = NULL;
211   const char *authtok_type = "";
212   int retval;
213
214   if (authtok == NULL || pamh->choice != PAM_CHAUTHTOK)
215     return PAM_SYSTEM_ERR;
216
217   if (prompt != NULL)
218     {
219       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
220                            _("Retype %s"), prompt);
221     }
222   else
223     {
224       retval = pam_get_item (pamh, PAM_AUTHTOK_TYPE, (const void **)&authtok_type);
225       if (retval != PAM_SUCCESS || authtok_type == NULL)
226         authtok_type = "";
227       retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
228                            PROMPT2, authtok_type,
229                            strlen (authtok_type) > 0?" ":"");
230     }
231
232   if (retval != PAM_SUCCESS || resp == NULL)
233     {
234       /* We want to abort the password change */
235       pam_set_item (pamh, PAM_AUTHTOK, NULL);
236       pam_error (pamh, _("Password change has been aborted."));
237       return PAM_AUTHTOK_ERR;
238     }
239
240   if (strcmp (*authtok, resp) != 0)
241     {
242       pam_set_item (pamh, PAM_AUTHTOK, NULL);
243       pam_error (pamh, MISTYPED_PASS);
244       _pam_overwrite (resp);
245       _pam_drop (resp);
246       return PAM_TRY_AGAIN;
247     }
248
249   retval = pam_set_item (pamh, PAM_AUTHTOK, resp);
250   _pam_overwrite (resp);
251   _pam_drop (resp);
252   if (retval != PAM_SUCCESS)
253     return retval;
254
255   return pam_get_item(pamh, PAM_AUTHTOK, (const void **)authtok);
256 }