1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /*
24 ** Ask for a password from tty
25 ** This is an own file to avoid conflicts with curses
26 */
27 #include <my_global.h>
28 #include <my_sys.h>
29 #include "mysql.h"
30 #include <m_string.h>
31 #include <m_ctype.h>
32 #include <mysql/get_password.h>
33
34 #ifdef HAVE_GETPASS
35 #ifdef HAVE_PWD_H
36 #include <pwd.h>
37 #endif /* HAVE_PWD_H */
38 #else /* ! HAVE_GETPASS */
39 #ifndef _WIN32
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 #ifdef HAVE_TERMIOS_H /* For tty-password */
44 #include <termios.h>
45 #define TERMIO struct termios
46 #else
47 #ifdef HAVE_TERMIO_H /* For tty-password */
48 #include <termio.h>
49 #define TERMIO struct termio
50 #else
51 #include <sgtty.h>
52 #define TERMIO struct sgttyb
53 #endif
54 #endif
55 #else
56 #include <conio.h>
57 #endif /* _WIN32 */
58 #endif /* HAVE_GETPASS */
59
60 #ifdef HAVE_GETPASSPHRASE /* For Solaris */
61 #define getpass(A) getpassphrase(A)
62 #endif
63
64 #ifdef _WIN32
65 /* were just going to fake it here and get input from
66 the keyboard */
67
get_tty_password_ext(const char * opt_message,strdup_handler_t strdup_function)68 char *get_tty_password_ext(const char *opt_message,
69 strdup_handler_t strdup_function)
70 {
71 char to[80];
72 char *pos=to,*end=to+sizeof(to)-1;
73 int i=0;
74 DBUG_ENTER("get_tty_password_ext");
75 _cputs(opt_message ? opt_message : "Enter password: ");
76 for (;;)
77 {
78 char tmp;
79 tmp=_getch();
80 if (tmp == '\b' || (int) tmp == 127)
81 {
82 if (pos != to)
83 {
84 _cputs("\b \b");
85 pos--;
86 continue;
87 }
88 }
89 if (tmp == '\n' || tmp == '\r' || tmp == 3)
90 break;
91 if (iscntrl(tmp) || pos == end)
92 continue;
93 _cputs("*");
94 *(pos++) = tmp;
95 }
96 while (pos != to && isspace(pos[-1]) == ' ')
97 pos--; /* Allow dummy space at end */
98 *pos=0;
99 _cputs("\n");
100 DBUG_RETURN(strdup_function(to,MYF(MY_FAE)));
101 }
102
103 #else
104
105
106 #ifndef HAVE_GETPASS
107 /*
108 ** Can't use fgets, because readline will get confused
109 ** length is max number of chars in to, not counting \0
110 * to will not include the eol characters.
111 */
112
get_password(char * to,uint length,int fd,my_bool echo)113 static void get_password(char *to,uint length,int fd, my_bool echo)
114 {
115 char *pos=to,*end=to+length;
116
117 for (;;)
118 {
119 char tmp;
120 if (my_read(fd,&tmp,1,MYF(0)) != 1)
121 break;
122 if (tmp == '\b' || (int) tmp == 127)
123 {
124 if (pos != to)
125 {
126 if (echo)
127 {
128 fputs("\b \b",stderr);
129 fflush(stderr);
130 }
131 pos--;
132 continue;
133 }
134 }
135 if (tmp == '\n' || tmp == '\r' || tmp == 3)
136 break;
137 if (iscntrl(tmp) || pos == end)
138 continue;
139 if (echo)
140 {
141 fputc('*',stderr);
142 fflush(stderr);
143 }
144 *(pos++) = tmp;
145 }
146 while (pos != to && isspace(pos[-1]) == ' ')
147 pos--; /* Allow dummy space at end */
148 *pos=0;
149 return;
150 }
151
152 #endif /* ! HAVE_GETPASS */
153
154
get_tty_password_ext(const char * opt_message,strdup_handler_t strdup_function)155 char *get_tty_password_ext(const char *opt_message,
156 strdup_handler_t strdup_function)
157 {
158 #ifdef HAVE_GETPASS
159 char *passbuff;
160 #else /* ! HAVE_GETPASS */
161 TERMIO org,tmp;
162 #endif /* HAVE_GETPASS */
163 char buff[80];
164
165 DBUG_ENTER("get_tty_password_ext");
166
167 #ifdef HAVE_GETPASS
168 passbuff = getpass(opt_message ? opt_message : "Enter password: ");
169
170 /* copy the password to buff and clear original (static) buffer */
171 my_stpnmov(buff, passbuff, sizeof(buff) - 1);
172 #ifdef _PASSWORD_LEN
173 memset(passbuff, 0, _PASSWORD_LEN);
174 #endif
175 #else
176 if (isatty(fileno(stderr)))
177 {
178 fputs(opt_message ? opt_message : "Enter password: ",stderr);
179 fflush(stderr);
180 }
181 #if defined(HAVE_TERMIOS_H)
182 tcgetattr(fileno(stdin), &org);
183 tmp = org;
184 tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
185 tmp.c_cc[VMIN] = 1;
186 tmp.c_cc[VTIME] = 0;
187 tcsetattr(fileno(stdin), TCSADRAIN, &tmp);
188 get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stderr)));
189 tcsetattr(fileno(stdin), TCSADRAIN, &org);
190 #elif defined(HAVE_TERMIO_H)
191 ioctl(fileno(stdin), (int) TCGETA, &org);
192 tmp=org;
193 tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
194 tmp.c_cc[VMIN] = 1;
195 tmp.c_cc[VTIME]= 0;
196 ioctl(fileno(stdin),(int) TCSETA, &tmp);
197 get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
198 ioctl(fileno(stdin),(int) TCSETA, &org);
199 #else
200 gtty(fileno(stdin), &org);
201 tmp=org;
202 tmp.sg_flags &= ~ECHO;
203 tmp.sg_flags |= RAW;
204 stty(fileno(stdin), &tmp);
205 get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr)));
206 stty(fileno(stdin), &org);
207 #endif
208 if (isatty(fileno(stderr)))
209 fputc('\n',stderr);
210 #endif /* HAVE_GETPASS */
211
212 DBUG_RETURN(strdup_function(buff,MYF(MY_FAE)));
213 }
214
215 #endif /* _WIN32 */
216
my_strdup_fct(const char * str,myf flags)217 static char * my_strdup_fct(const char *str, myf flags)
218 {
219 return my_strdup(PSI_NOT_INSTRUMENTED, str, flags);
220 }
221
get_tty_password(const char * opt_message)222 char *get_tty_password(const char *opt_message)
223 {
224 return get_tty_password_ext(opt_message, my_strdup_fct);
225 }
226