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