Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libpam / libpam / pam_get_pass.c
1 /*-
2  * Copyright 1998 Juniper Networks, Inc.
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: src/lib/libpam/libpam/pam_get_pass.c,v 1.1.1.1.6.3 2002/07/04 13:05:34 des Exp $");
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <security/pam_modules.h>
34 #include <security/pam_mod_misc.h>
35
36 static int       pam_conv_pass(pam_handle_t *, const char *, struct options *);
37
38 static int
39 pam_conv_pass(pam_handle_t *pamh, const char *prompt, struct options *options)
40 {
41         const struct pam_conv *conv;
42         struct pam_message msg;
43         const struct pam_message *msgs[1];
44         struct pam_response *resp;
45         const void *item;
46         int retval;
47
48         retval = pam_get_item(pamh, PAM_CONV, &item);
49         if (retval != PAM_SUCCESS)
50                 return retval;
51         conv = (const struct pam_conv *)item;
52         msg.msg_style = pam_test_option(options, PAM_OPT_ECHO_PASS, NULL) ?
53             PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
54         msg.msg = prompt;
55         msgs[0] = &msg;
56         retval = conv->conv(1, msgs, &resp, conv->appdata_ptr);
57         if (retval != PAM_SUCCESS)
58                 return retval;
59         retval = pam_set_item(pamh, PAM_AUTHTOK, resp[0].resp);
60         if (retval != PAM_SUCCESS)
61                 return retval;
62         memset(resp[0].resp, 0, strlen(resp[0].resp));
63         free(resp[0].resp);
64         free(resp);
65         return PAM_SUCCESS;
66 }
67
68 int
69 pam_get_pass(pam_handle_t *pamh, const char **passp, const char *prompt,
70     struct options *options)
71 {
72         int retval;
73         const void *item = NULL;
74
75         /*
76          * Grab the already-entered password if we might want to use it.
77          */
78         if (pam_test_option(options, PAM_OPT_TRY_FIRST_PASS, NULL) ||
79             pam_test_option(options, PAM_OPT_USE_FIRST_PASS, NULL)) {
80                 retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
81                 if (retval != PAM_SUCCESS)
82                         return retval;
83         }
84
85         if (item == NULL) {
86                 /* The user hasn't entered a password yet. */
87                 if (pam_test_option(options, PAM_OPT_USE_FIRST_PASS, NULL))
88                         return PAM_AUTH_ERR;
89                 /* Use the conversation function to get a password. */
90                 retval = pam_conv_pass(pamh, prompt, options);
91                 if (retval != PAM_SUCCESS)
92                         return retval;
93                 retval = pam_get_item(pamh, PAM_AUTHTOK, &item);
94                 if (retval != PAM_SUCCESS)
95                         return retval;
96         }
97         *passp = (const char *)item;
98         return PAM_SUCCESS;
99 }