xref: /aosp_15_r20/external/curl/src/tool_getpass.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "tool_setup.h"
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #if defined(__AMIGA__) && !defined(__amigaos4__)
27*6236dae4SAndroid Build Coastguard Worker #  undef HAVE_TERMIOS_H
28*6236dae4SAndroid Build Coastguard Worker #endif
29*6236dae4SAndroid Build Coastguard Worker 
30*6236dae4SAndroid Build Coastguard Worker #ifndef HAVE_GETPASS_R
31*6236dae4SAndroid Build Coastguard Worker /* this file is only for systems without getpass_r() */
32*6236dae4SAndroid Build Coastguard Worker 
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
34*6236dae4SAndroid Build Coastguard Worker #  include <fcntl.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker 
37*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_TERMIOS_H
38*6236dae4SAndroid Build Coastguard Worker #  include <termios.h>
39*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_TERMIO_H)
40*6236dae4SAndroid Build Coastguard Worker #  include <termio.h>
41*6236dae4SAndroid Build Coastguard Worker #endif
42*6236dae4SAndroid Build Coastguard Worker 
43*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
44*6236dae4SAndroid Build Coastguard Worker #  include descrip
45*6236dae4SAndroid Build Coastguard Worker #  include starlet
46*6236dae4SAndroid Build Coastguard Worker #  include iodef
47*6236dae4SAndroid Build Coastguard Worker #endif
48*6236dae4SAndroid Build Coastguard Worker 
49*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
50*6236dae4SAndroid Build Coastguard Worker #  include <conio.h>
51*6236dae4SAndroid Build Coastguard Worker #endif
52*6236dae4SAndroid Build Coastguard Worker 
53*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_UNISTD_H
54*6236dae4SAndroid Build Coastguard Worker #include <unistd.h>
55*6236dae4SAndroid Build Coastguard Worker #endif
56*6236dae4SAndroid Build Coastguard Worker #include "tool_getpass.h"
57*6236dae4SAndroid Build Coastguard Worker 
58*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h" /* keep this as LAST include */
59*6236dae4SAndroid Build Coastguard Worker 
60*6236dae4SAndroid Build Coastguard Worker #ifdef __VMS
61*6236dae4SAndroid Build Coastguard Worker /* VMS implementation */
getpass_r(const char * prompt,char * buffer,size_t buflen)62*6236dae4SAndroid Build Coastguard Worker char *getpass_r(const char *prompt, char *buffer, size_t buflen)
63*6236dae4SAndroid Build Coastguard Worker {
64*6236dae4SAndroid Build Coastguard Worker   long sts;
65*6236dae4SAndroid Build Coastguard Worker   short chan;
66*6236dae4SAndroid Build Coastguard Worker 
67*6236dae4SAndroid Build Coastguard Worker   /* MSK, 23-JAN-2004, iosbdef.h was not in VAX V7.2 or CC 6.4  */
68*6236dae4SAndroid Build Coastguard Worker   /* distribution so I created this. May revert back later to */
69*6236dae4SAndroid Build Coastguard Worker   /* struct _iosb iosb;                                        */
70*6236dae4SAndroid Build Coastguard Worker   struct _iosb
71*6236dae4SAndroid Build Coastguard Worker      {
72*6236dae4SAndroid Build Coastguard Worker      short int iosb$w_status; /* status     */
73*6236dae4SAndroid Build Coastguard Worker      short int iosb$w_bcnt;   /* byte count */
74*6236dae4SAndroid Build Coastguard Worker      int       unused;        /* unused     */
75*6236dae4SAndroid Build Coastguard Worker      } iosb;
76*6236dae4SAndroid Build Coastguard Worker 
77*6236dae4SAndroid Build Coastguard Worker   $DESCRIPTOR(ttdesc, "TT");
78*6236dae4SAndroid Build Coastguard Worker 
79*6236dae4SAndroid Build Coastguard Worker   buffer[0] = '\0';
80*6236dae4SAndroid Build Coastguard Worker   sts = sys$assign(&ttdesc, &chan, 0, 0);
81*6236dae4SAndroid Build Coastguard Worker   if(sts & 1) {
82*6236dae4SAndroid Build Coastguard Worker     sts = sys$qiow(0, chan,
83*6236dae4SAndroid Build Coastguard Worker                    IO$_READPROMPT | IO$M_NOECHO,
84*6236dae4SAndroid Build Coastguard Worker                    &iosb, 0, 0, buffer, buflen, 0, 0,
85*6236dae4SAndroid Build Coastguard Worker                    prompt, strlen(prompt));
86*6236dae4SAndroid Build Coastguard Worker 
87*6236dae4SAndroid Build Coastguard Worker     if((sts & 1) && (iosb.iosb$w_status & 1))
88*6236dae4SAndroid Build Coastguard Worker       buffer[iosb.iosb$w_bcnt] = '\0';
89*6236dae4SAndroid Build Coastguard Worker 
90*6236dae4SAndroid Build Coastguard Worker     sys$dassgn(chan);
91*6236dae4SAndroid Build Coastguard Worker   }
92*6236dae4SAndroid Build Coastguard Worker   return buffer; /* we always return success */
93*6236dae4SAndroid Build Coastguard Worker }
94*6236dae4SAndroid Build Coastguard Worker #define DONE
95*6236dae4SAndroid Build Coastguard Worker #endif /* __VMS */
96*6236dae4SAndroid Build Coastguard Worker 
97*6236dae4SAndroid Build Coastguard Worker #if defined(_WIN32)
98*6236dae4SAndroid Build Coastguard Worker 
getpass_r(const char * prompt,char * buffer,size_t buflen)99*6236dae4SAndroid Build Coastguard Worker char *getpass_r(const char *prompt, char *buffer, size_t buflen)
100*6236dae4SAndroid Build Coastguard Worker {
101*6236dae4SAndroid Build Coastguard Worker   size_t i;
102*6236dae4SAndroid Build Coastguard Worker   fputs(prompt, tool_stderr);
103*6236dae4SAndroid Build Coastguard Worker 
104*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < buflen; i++) {
105*6236dae4SAndroid Build Coastguard Worker     buffer[i] = (char)getch();
106*6236dae4SAndroid Build Coastguard Worker     if(buffer[i] == '\r' || buffer[i] == '\n') {
107*6236dae4SAndroid Build Coastguard Worker       buffer[i] = '\0';
108*6236dae4SAndroid Build Coastguard Worker       break;
109*6236dae4SAndroid Build Coastguard Worker     }
110*6236dae4SAndroid Build Coastguard Worker     else
111*6236dae4SAndroid Build Coastguard Worker       if(buffer[i] == '\b')
112*6236dae4SAndroid Build Coastguard Worker         /* remove this letter and if this is not the first key, remove the
113*6236dae4SAndroid Build Coastguard Worker            previous one as well */
114*6236dae4SAndroid Build Coastguard Worker         i = i - (i >= 1 ? 2 : 1);
115*6236dae4SAndroid Build Coastguard Worker   }
116*6236dae4SAndroid Build Coastguard Worker   /* since echo is disabled, print a newline */
117*6236dae4SAndroid Build Coastguard Worker   fputs("\n", tool_stderr);
118*6236dae4SAndroid Build Coastguard Worker   /* if user did not hit ENTER, terminate buffer */
119*6236dae4SAndroid Build Coastguard Worker   if(i == buflen)
120*6236dae4SAndroid Build Coastguard Worker     buffer[buflen-1] = '\0';
121*6236dae4SAndroid Build Coastguard Worker 
122*6236dae4SAndroid Build Coastguard Worker   return buffer; /* we always return success */
123*6236dae4SAndroid Build Coastguard Worker }
124*6236dae4SAndroid Build Coastguard Worker #define DONE
125*6236dae4SAndroid Build Coastguard Worker #endif /* _WIN32 */
126*6236dae4SAndroid Build Coastguard Worker 
127*6236dae4SAndroid Build Coastguard Worker #ifndef DONE /* not previously provided */
128*6236dae4SAndroid Build Coastguard Worker 
129*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_TERMIOS_H
130*6236dae4SAndroid Build Coastguard Worker #  define struct_term  struct termios
131*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_TERMIO_H)
132*6236dae4SAndroid Build Coastguard Worker #  define struct_term  struct termio
133*6236dae4SAndroid Build Coastguard Worker #else
134*6236dae4SAndroid Build Coastguard Worker #  undef  struct_term
135*6236dae4SAndroid Build Coastguard Worker #endif
136*6236dae4SAndroid Build Coastguard Worker 
ttyecho(bool enable,int fd)137*6236dae4SAndroid Build Coastguard Worker static bool ttyecho(bool enable, int fd)
138*6236dae4SAndroid Build Coastguard Worker {
139*6236dae4SAndroid Build Coastguard Worker #ifdef struct_term
140*6236dae4SAndroid Build Coastguard Worker   static struct_term withecho;
141*6236dae4SAndroid Build Coastguard Worker   static struct_term noecho;
142*6236dae4SAndroid Build Coastguard Worker #endif
143*6236dae4SAndroid Build Coastguard Worker   if(!enable) {
144*6236dae4SAndroid Build Coastguard Worker     /* disable echo by extracting the current 'withecho' mode and remove the
145*6236dae4SAndroid Build Coastguard Worker        ECHO bit and set back the struct */
146*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_TERMIOS_H
147*6236dae4SAndroid Build Coastguard Worker     tcgetattr(fd, &withecho);
148*6236dae4SAndroid Build Coastguard Worker     noecho = withecho;
149*6236dae4SAndroid Build Coastguard Worker     noecho.c_lflag &= ~(tcflag_t)ECHO;
150*6236dae4SAndroid Build Coastguard Worker     tcsetattr(fd, TCSANOW, &noecho);
151*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_TERMIO_H)
152*6236dae4SAndroid Build Coastguard Worker     ioctl(fd, TCGETA, &withecho);
153*6236dae4SAndroid Build Coastguard Worker     noecho = withecho;
154*6236dae4SAndroid Build Coastguard Worker     noecho.c_lflag &= ~(tcflag_t)ECHO;
155*6236dae4SAndroid Build Coastguard Worker     ioctl(fd, TCSETA, &noecho);
156*6236dae4SAndroid Build Coastguard Worker #else
157*6236dae4SAndroid Build Coastguard Worker     /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we cannot disable echo! */
158*6236dae4SAndroid Build Coastguard Worker     (void)fd;
159*6236dae4SAndroid Build Coastguard Worker     return FALSE; /* not disabled */
160*6236dae4SAndroid Build Coastguard Worker #endif
161*6236dae4SAndroid Build Coastguard Worker     return TRUE; /* disabled */
162*6236dae4SAndroid Build Coastguard Worker   }
163*6236dae4SAndroid Build Coastguard Worker   /* re-enable echo, assumes we disabled it before (and set the structs we
164*6236dae4SAndroid Build Coastguard Worker      now use to reset the terminal status) */
165*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_TERMIOS_H
166*6236dae4SAndroid Build Coastguard Worker   tcsetattr(fd, TCSAFLUSH, &withecho);
167*6236dae4SAndroid Build Coastguard Worker #elif defined(HAVE_TERMIO_H)
168*6236dae4SAndroid Build Coastguard Worker   ioctl(fd, TCSETA, &withecho);
169*6236dae4SAndroid Build Coastguard Worker #else
170*6236dae4SAndroid Build Coastguard Worker   return FALSE; /* not enabled */
171*6236dae4SAndroid Build Coastguard Worker #endif
172*6236dae4SAndroid Build Coastguard Worker   return TRUE; /* enabled */
173*6236dae4SAndroid Build Coastguard Worker }
174*6236dae4SAndroid Build Coastguard Worker 
getpass_r(const char * prompt,char * password,size_t buflen)175*6236dae4SAndroid Build Coastguard Worker char *getpass_r(const char *prompt, /* prompt to display */
176*6236dae4SAndroid Build Coastguard Worker                 char *password,     /* buffer to store password in */
177*6236dae4SAndroid Build Coastguard Worker                 size_t buflen)      /* size of buffer to store password in */
178*6236dae4SAndroid Build Coastguard Worker {
179*6236dae4SAndroid Build Coastguard Worker   ssize_t nread;
180*6236dae4SAndroid Build Coastguard Worker   bool disabled;
181*6236dae4SAndroid Build Coastguard Worker   int fd = open("/dev/tty", O_RDONLY);
182*6236dae4SAndroid Build Coastguard Worker   if(-1 == fd)
183*6236dae4SAndroid Build Coastguard Worker     fd = STDIN_FILENO; /* use stdin if the tty could not be used */
184*6236dae4SAndroid Build Coastguard Worker 
185*6236dae4SAndroid Build Coastguard Worker   disabled = ttyecho(FALSE, fd); /* disable terminal echo */
186*6236dae4SAndroid Build Coastguard Worker 
187*6236dae4SAndroid Build Coastguard Worker   fputs(prompt, tool_stderr);
188*6236dae4SAndroid Build Coastguard Worker   nread = read(fd, password, buflen);
189*6236dae4SAndroid Build Coastguard Worker   if(nread > 0)
190*6236dae4SAndroid Build Coastguard Worker     password[--nread] = '\0'; /* null-terminate where enter is stored */
191*6236dae4SAndroid Build Coastguard Worker   else
192*6236dae4SAndroid Build Coastguard Worker     password[0] = '\0'; /* got nothing */
193*6236dae4SAndroid Build Coastguard Worker 
194*6236dae4SAndroid Build Coastguard Worker   if(disabled) {
195*6236dae4SAndroid Build Coastguard Worker     /* if echo actually was disabled, add a newline */
196*6236dae4SAndroid Build Coastguard Worker     fputs("\n", tool_stderr);
197*6236dae4SAndroid Build Coastguard Worker     (void)ttyecho(TRUE, fd); /* enable echo */
198*6236dae4SAndroid Build Coastguard Worker   }
199*6236dae4SAndroid Build Coastguard Worker 
200*6236dae4SAndroid Build Coastguard Worker   if(STDIN_FILENO != fd)
201*6236dae4SAndroid Build Coastguard Worker     close(fd);
202*6236dae4SAndroid Build Coastguard Worker 
203*6236dae4SAndroid Build Coastguard Worker   return password; /* return pointer to buffer */
204*6236dae4SAndroid Build Coastguard Worker }
205*6236dae4SAndroid Build Coastguard Worker 
206*6236dae4SAndroid Build Coastguard Worker #endif /* DONE */
207*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_GETPASS_R */
208