1*10296SHuie-Ying.Lee@Sun.COM /*
2*10296SHuie-Ying.Lee@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3*10296SHuie-Ying.Lee@Sun.COM * Use is subject to license terms.
4*10296SHuie-Ying.Lee@Sun.COM */
5*10296SHuie-Ying.Lee@Sun.COM
60Sstevel@tonic-gate /*
70Sstevel@tonic-gate * Copyright (c) 2001 Markus Friedl. All rights reserved.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
100Sstevel@tonic-gate * modification, are permitted provided that the following conditions
110Sstevel@tonic-gate * are met:
120Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
150Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
160Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
170Sstevel@tonic-gate *
180Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
190Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
200Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
210Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
220Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
230Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
240Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
250Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
260Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
270Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include "includes.h"
310Sstevel@tonic-gate RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $");
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include "xmalloc.h"
340Sstevel@tonic-gate #include "readpass.h"
350Sstevel@tonic-gate #include "pathnames.h"
360Sstevel@tonic-gate #include "log.h"
370Sstevel@tonic-gate #include "ssh.h"
38*10296SHuie-Ying.Lee@Sun.COM #include <langinfo.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate static char *
ssh_askpass(char * askpass,const char * msg)410Sstevel@tonic-gate ssh_askpass(char *askpass, const char *msg)
420Sstevel@tonic-gate {
430Sstevel@tonic-gate pid_t pid;
440Sstevel@tonic-gate size_t len;
450Sstevel@tonic-gate char *pass;
460Sstevel@tonic-gate int p[2], status, ret;
470Sstevel@tonic-gate char buf[1024];
480Sstevel@tonic-gate
490Sstevel@tonic-gate if (fflush(stdout) != 0)
500Sstevel@tonic-gate error("ssh_askpass: fflush: %s", strerror(errno));
510Sstevel@tonic-gate if (askpass == NULL)
520Sstevel@tonic-gate fatal("internal error: askpass undefined");
530Sstevel@tonic-gate if (pipe(p) < 0) {
540Sstevel@tonic-gate error("ssh_askpass: pipe: %s", strerror(errno));
550Sstevel@tonic-gate return xstrdup("");
560Sstevel@tonic-gate }
570Sstevel@tonic-gate if ((pid = fork()) < 0) {
580Sstevel@tonic-gate error("ssh_askpass: fork: %s", strerror(errno));
590Sstevel@tonic-gate return xstrdup("");
600Sstevel@tonic-gate }
610Sstevel@tonic-gate if (pid == 0) {
620Sstevel@tonic-gate seteuid(getuid());
630Sstevel@tonic-gate setuid(getuid());
640Sstevel@tonic-gate close(p[0]);
650Sstevel@tonic-gate if (dup2(p[1], STDOUT_FILENO) < 0)
660Sstevel@tonic-gate fatal("ssh_askpass: dup2: %s", strerror(errno));
670Sstevel@tonic-gate execlp(askpass, askpass, msg, (char *) 0);
680Sstevel@tonic-gate fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
690Sstevel@tonic-gate }
700Sstevel@tonic-gate close(p[1]);
710Sstevel@tonic-gate
720Sstevel@tonic-gate len = ret = 0;
730Sstevel@tonic-gate do {
740Sstevel@tonic-gate ret = read(p[0], buf + len, sizeof(buf) - 1 - len);
750Sstevel@tonic-gate if (ret == -1 && errno == EINTR)
760Sstevel@tonic-gate continue;
770Sstevel@tonic-gate if (ret <= 0)
780Sstevel@tonic-gate break;
790Sstevel@tonic-gate len += ret;
800Sstevel@tonic-gate } while (sizeof(buf) - 1 - len > 0);
810Sstevel@tonic-gate buf[len] = '\0';
820Sstevel@tonic-gate
830Sstevel@tonic-gate close(p[0]);
840Sstevel@tonic-gate while (waitpid(pid, &status, 0) < 0)
850Sstevel@tonic-gate if (errno != EINTR)
860Sstevel@tonic-gate break;
870Sstevel@tonic-gate
880Sstevel@tonic-gate buf[strcspn(buf, "\r\n")] = '\0';
890Sstevel@tonic-gate pass = xstrdup(buf);
900Sstevel@tonic-gate memset(buf, 0, sizeof(buf));
910Sstevel@tonic-gate return pass;
920Sstevel@tonic-gate }
930Sstevel@tonic-gate
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate * Reads a passphrase from /dev/tty with echo turned off/on. Returns the
960Sstevel@tonic-gate * passphrase (allocated with xmalloc). Exits if EOF is encountered. If
970Sstevel@tonic-gate * RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no
980Sstevel@tonic-gate * tty is available
990Sstevel@tonic-gate */
1000Sstevel@tonic-gate char *
read_passphrase(const char * prompt,int flags)1010Sstevel@tonic-gate read_passphrase(const char *prompt, int flags)
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate char *askpass = NULL, *ret, buf[1024];
1040Sstevel@tonic-gate int rppflags, use_askpass = 0, ttyfd;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
1070Sstevel@tonic-gate if (flags & RP_ALLOW_STDIN) {
1080Sstevel@tonic-gate if (!isatty(STDIN_FILENO))
1090Sstevel@tonic-gate use_askpass = 1;
1100Sstevel@tonic-gate } else {
1110Sstevel@tonic-gate rppflags |= RPP_REQUIRE_TTY;
1120Sstevel@tonic-gate ttyfd = open(_PATH_TTY, O_RDWR);
1130Sstevel@tonic-gate if (ttyfd >= 0)
1140Sstevel@tonic-gate close(ttyfd);
1150Sstevel@tonic-gate else
1160Sstevel@tonic-gate use_askpass = 1;
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate if (use_askpass && getenv("DISPLAY")) {
1200Sstevel@tonic-gate if (getenv(SSH_ASKPASS_ENV))
1210Sstevel@tonic-gate askpass = getenv(SSH_ASKPASS_ENV);
1220Sstevel@tonic-gate else
1230Sstevel@tonic-gate askpass = _PATH_SSH_ASKPASS_DEFAULT;
1240Sstevel@tonic-gate return ssh_askpass(askpass, prompt);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
1280Sstevel@tonic-gate if (flags & RP_ALLOW_EOF)
1290Sstevel@tonic-gate return NULL;
1300Sstevel@tonic-gate return xstrdup("");
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate ret = xstrdup(buf);
1340Sstevel@tonic-gate memset(buf, 'x', sizeof buf);
1350Sstevel@tonic-gate return ret;
1360Sstevel@tonic-gate }
137*10296SHuie-Ying.Lee@Sun.COM
138*10296SHuie-Ying.Lee@Sun.COM int
ask_permission(const char * fmt,...)139*10296SHuie-Ying.Lee@Sun.COM ask_permission(const char *fmt, ...)
140*10296SHuie-Ying.Lee@Sun.COM {
141*10296SHuie-Ying.Lee@Sun.COM va_list args;
142*10296SHuie-Ying.Lee@Sun.COM char *p, prompt[1024];
143*10296SHuie-Ying.Lee@Sun.COM int allowed = 0;
144*10296SHuie-Ying.Lee@Sun.COM char *yeschar = nl_langinfo(YESSTR);
145*10296SHuie-Ying.Lee@Sun.COM
146*10296SHuie-Ying.Lee@Sun.COM va_start(args, fmt);
147*10296SHuie-Ying.Lee@Sun.COM vsnprintf(prompt, sizeof(prompt), fmt, args);
148*10296SHuie-Ying.Lee@Sun.COM va_end(args);
149*10296SHuie-Ying.Lee@Sun.COM
150*10296SHuie-Ying.Lee@Sun.COM p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
151*10296SHuie-Ying.Lee@Sun.COM if (p != NULL) {
152*10296SHuie-Ying.Lee@Sun.COM /*
153*10296SHuie-Ying.Lee@Sun.COM * Accept empty responses and responses consisting
154*10296SHuie-Ying.Lee@Sun.COM * of the word "yes" as affirmative.
155*10296SHuie-Ying.Lee@Sun.COM */
156*10296SHuie-Ying.Lee@Sun.COM if (*p == '\0' || *p == '\n' ||
157*10296SHuie-Ying.Lee@Sun.COM strncasecmp(p, yeschar, 1) == 0)
158*10296SHuie-Ying.Lee@Sun.COM allowed = 1;
159*10296SHuie-Ying.Lee@Sun.COM xfree(p);
160*10296SHuie-Ying.Lee@Sun.COM }
161*10296SHuie-Ying.Lee@Sun.COM
162*10296SHuie-Ying.Lee@Sun.COM return (allowed);
163*10296SHuie-Ying.Lee@Sun.COM }
164