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