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