2 * Unix SMB/CIFS implementation.
4 * getpass.c - platform independent getpass function.
6 * Copyright (c) 2010-2012 Andreas Schneider <asn@samba.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "system/filesys.h"
25 #include "system/terminal.h"
27 #if !defined(SMB_MALLOC)
29 #define SMB_MALLOC(s) malloc((s))
35 * @brief Get the password from the console.
37 * @param[in] prompt The prompt to display.
39 * @param[in] buf The buffer to fill.
41 * @param[in] len The length of the buffer.
43 * @param[in] verify Should the password be verified?
45 * @return 1 on success, 0 on error.
47 static int samba_gets(const char *prompt
, char *buf
, size_t len
, bool verify
)
53 tmp
= SMB_MALLOC(len
);
59 /* read the password */
62 fprintf(stdout
, "%s[%s] ", prompt
, buf
);
64 fprintf(stdout
, "%s", prompt
);
67 if (fgets(tmp
, len
, stdin
) == NULL
) {
72 if ((ptr
= strchr(tmp
, '\n'))) {
75 fprintf(stdout
, "\n");
78 strncpy(buf
, tmp
, len
);
84 key_string
= SMB_MALLOC(len
);
85 if (key_string
== NULL
) {
88 memset(key_string
, '\0', len
);
90 fprintf(stdout
, "\nVerifying, please re-enter. %s", prompt
);
92 if (! fgets(key_string
, len
, stdin
)) {
93 memset(key_string
, '\0', len
);
94 SAFE_FREE(key_string
);
98 if ((ptr
= strchr(key_string
, '\n'))) {
101 fprintf(stdout
, "\n");
102 if (strcmp(buf
, key_string
)) {
103 printf("\n\07\07Mismatch - try again\n");
104 memset(key_string
, '\0', len
);
105 SAFE_FREE(key_string
);
109 memset(key_string
, '\0', len
);
110 SAFE_FREE(key_string
);
114 memset(tmp
, '\0', len
);
121 * @brief Get a password from the console.
123 * You should make sure that the buffer is an empty string!
125 * You can also use this function to ask for a username. Then you can fill the
126 * buffer with the username and it is shows to the users. If the users just
127 * presses enter the buffer will be untouched.
130 * char username[128];
132 * snprintf(username, sizeof(username), "john");
134 * samba_getpass("Username:", username, sizeof(username), 1, 0);
137 * The prompt will look like this:
141 * If you press enter then john is used as the username, or you can type it in
144 * @param[in] prompt The prompt to show to ask for the password.
146 * @param[out] buf The buffer the password should be stored. It NEEDS to be
147 * empty or filled out.
149 * @param[in] len The length of the buffer.
151 * @param[in] echo Should we echo what you type.
153 * @param[in] verify Should we ask for the password twice.
155 * @return 0 on success, -1 on error.
157 int samba_getpass(const char *prompt
,
164 struct termios old_attr
;
168 /* fgets needs at least len - 1 */
169 if (prompt
== NULL
|| buf
== NULL
|| len
< 2) {
173 if (isatty (STDIN_FILENO
)) {
176 ZERO_STRUCT(old_attr
);
178 /* get local terminal attributes */
179 if (tcgetattr(STDIN_FILENO
, &attr
) < 0) {
184 /* save terminal attributes */
185 memcpy(&old_attr
, &attr
, sizeof(attr
));
186 if((fd
= fcntl(0, F_GETFL
, 0)) < 0) {
193 attr
.c_lflag
&= ~(ECHO
);
196 /* write attributes to terminal */
197 if (tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &attr
) < 0) {
203 /* disable nonblocking I/O */
205 fcntl(0, F_SETFL
, fd
& ~O_NDELAY
);
208 ok
= samba_gets(prompt
, buf
, len
, verify
);
210 if (isatty (STDIN_FILENO
)) {
213 tcsetattr(STDIN_FILENO
, TCSANOW
, &old_attr
);
218 fcntl(0, F_SETFL
, fd
);
222 memset (buf
, '\0', len
);
226 /* force termination */