1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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 #if defined(HAVE_BROKEN_GETPASS) && !defined(HAVE_GETPASSPHRASE)
39 #undef HAVE_GETPASS
40 #endif
41 
42 #ifdef HAVE_GETPASS
43 #ifdef HAVE_PWD_H
44 #include <pwd.h>
45 #endif /* HAVE_PWD_H */
46 #else /* ! HAVE_GETPASS */
47 #if !defined(__WIN__)
48 #include <sys/ioctl.h>
49 #ifdef HAVE_TERMIOS_H				/* For tty-password */
50 #include	<termios.h>
51 #define TERMIO	struct termios
52 #else
53 #ifdef HAVE_TERMIO_H				/* For tty-password */
54 #include	<termio.h>
55 #define TERMIO	struct termio
56 #else
57 #include	<sgtty.h>
58 #define TERMIO	struct sgttyb
59 #endif
60 #endif
61 #ifdef alpha_linux_port
62 #include <asm/ioctls.h>				/* QQ; Fix this in configure */
63 #include <asm/termiobits.h>
64 #endif
65 #else
66 #include <conio.h>
67 #endif /* __WIN__ */
68 #endif /* HAVE_GETPASS */
69 
70 #ifdef HAVE_GETPASSPHRASE			/* For Solaris */
71 #define getpass(A) getpassphrase(A)
72 #endif
73 
74 #if defined(__WIN__)
75 /* were just going to fake it here and get input from the keyboard */
get_tty_password(const char * opt_message)76 char *get_tty_password(const char *opt_message)
77 {
78   char to[80];
79   char *pos=to,*end=to+sizeof(to)-1;
80   int i=0;
81   DBUG_ENTER("get_tty_password");
82   _cputs(opt_message ? opt_message : "Enter password: ");
83   for (;;)
84   {
85     char tmp;
86     tmp=_getch();
87     if (tmp == '\b' || (int) tmp == 127)
88     {
89       if (pos != to)
90       {
91 	_cputs("\b \b");
92 	pos--;
93 	continue;
94       }
95     }
96     if (tmp == '\n' || tmp == '\r' || tmp == 3)
97       break;
98     if (iscntrl(tmp) || pos == end)
99       continue;
100     _cputs("*");
101     *(pos++) = tmp;
102   }
103   while (pos != to && isspace(pos[-1]) == ' ')
104     pos--;					/* Allow dummy space at end */
105   *pos=0;
106   _cputs("\n");
107   DBUG_RETURN(my_strdup(to,MYF(MY_FAE)));
108 }
109 
110 #else
111 
112 #ifndef HAVE_GETPASS
113 /*
114   Can't use fgets, because readline will get confused
115   length is max number of chars in to, not counting \0
116   to will not include the eol characters.
117 */
118 
get_password(char * to,uint length,int fd,my_bool echo)119 static void get_password(char *to,uint length,int fd, my_bool echo)
120 {
121   char *pos=to,*end=to+length;
122 
123   for (;;)
124   {
125     char tmp;
126     if (my_read(fd,&tmp,1,MYF(0)) != 1)
127       break;
128     if (tmp == '\b' || (int) tmp == 127)
129     {
130       if (pos != to)
131       {
132 	if (echo)
133 	{
134 	  fputs("\b \b",stdout);
135 	  fflush(stdout);
136 	}
137 	pos--;
138 	continue;
139       }
140     }
141     if (tmp == '\n' || tmp == '\r' || tmp == 3)
142       break;
143     if (iscntrl(tmp) || pos == end)
144       continue;
145     if (echo)
146     {
147       fputc('*',stdout);
148       fflush(stdout);
149     }
150     *(pos++) = tmp;
151   }
152   while (pos != to && isspace(pos[-1]) == ' ')
153     pos--;					/* Allow dummy space at end */
154   *pos=0;
155   return;
156 }
157 #endif /* ! HAVE_GETPASS */
158 
159 
get_tty_password(const char * opt_message)160 char *get_tty_password(const char *opt_message)
161 {
162 #ifdef HAVE_GETPASS
163   char *passbuff;
164 #else /* ! HAVE_GETPASS */
165   TERMIO org,tmp;
166 #endif /* HAVE_GETPASS */
167   char buff[80];
168 
169   DBUG_ENTER("get_tty_password");
170 
171 #ifdef HAVE_GETPASS
172   passbuff = getpass(opt_message ? opt_message : "Enter password: ");
173 
174   /* copy the password to buff and clear original (static) buffer */
175   strnmov(buff, passbuff, sizeof(buff) - 1);
176 #ifdef _PASSWORD_LEN
177   memset(passbuff, 0, _PASSWORD_LEN);
178 #endif
179 #else
180   if (isatty(fileno(stdout)))
181   {
182     fputs(opt_message ? opt_message : "Enter password: ",stdout);
183     fflush(stdout);
184   }
185 #if defined(HAVE_TERMIOS_H)
186   tcgetattr(fileno(stdin), &org);
187   tmp = org;
188   tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
189   tmp.c_cc[VMIN] = 1;
190   tmp.c_cc[VTIME] = 0;
191   tcsetattr(fileno(stdin), TCSADRAIN, &tmp);
192   get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stdout)));
193   tcsetattr(fileno(stdin), TCSADRAIN, &org);
194 #elif defined(HAVE_TERMIO_H)
195   ioctl(fileno(stdin), (int) TCGETA, &org);
196   tmp=org;
197   tmp.c_lflag &= ~(ECHO | ISIG | ICANON);
198   tmp.c_cc[VMIN] = 1;
199   tmp.c_cc[VTIME]= 0;
200   ioctl(fileno(stdin),(int) TCSETA, &tmp);
201   get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stdout)));
202   ioctl(fileno(stdin),(int) TCSETA, &org);
203 #else
204   gtty(fileno(stdin), &org);
205   tmp=org;
206   tmp.sg_flags &= ~ECHO;
207   tmp.sg_flags |= RAW;
208   stty(fileno(stdin), &tmp);
209   get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stdout)));
210   stty(fileno(stdin), &org);
211 #endif
212   if (isatty(fileno(stdout)))
213     fputc('\n',stdout);
214 #endif /* HAVE_GETPASS */
215 
216   DBUG_RETURN(my_strdup(buff,MYF(MY_FAE)));
217 }
218 #endif /*__WIN__*/
219