NetBSD Problem Report #10955

Received: (qmail 27133 invoked from network); 5 Sep 2000 17:39:06 -0000
Message-Id: <200009051739.NAA24182@hrothgar.gw.com>
Date: Tue, 5 Sep 2000 13:39:05 -0400 (EDT)
From: christos@zoulas.com
Reply-To: christos@zoulas.com
To: gnats-bugs@gnats.netbsd.org
Subject: getpass(3) implementations are inconsistent
X-Send-Pr-Version: 3.95

>Number:         10955
>Category:       lib
>Synopsis:       libc getpass(3) blocks signals.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kamil
>State:          closed
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 05 17:40:00 +0000 2000
>Closed-Date:    Sat Oct 07 14:06:04 +0000 2017
>Last-Modified:  Sat Oct 07 14:06:04 +0000 2017
>Originator:     Christos Zoulas
>Release:        Tue Sep  5 13:26:41 EDT 2000
>Organization:
	None, but I am trying.
>Environment:
System: NetBSD hrothgar.gw.com 1.4.2A NetBSD 1.4.2A (GW-GENERIC) #6: Wed May 31 06:12:46 EEST 2000 kim@pyry.gw.com:/net/pyry/src-2/NetBSD/cvsroot/src/sys/arch/i386/compile/GW-GENERIC i386


>Description:
	Unfortunately many programs that need getpass(3) [su, kerberos,
	ssh] don't use the standard getpass(3) implementation from libc,
	but roll their own leasing to inconsistent behavior. All other
	getpass(3) implementations trap signals, but the libc one does
	not. This getpass implementation, traps signals and uses raw
	reads/writes and non-canonical tty processing to achive the
	desired result.
	I.e.
	% su
	Password: 123^Z
	Suspended
	% fg
	456\n
	# makes the su program see 123456 as the password.

>How-To-Repeat:
	Hit control-C or control-Z when typing a password.
>Fix:

	Replace getpass() with the following implementation.

/*	$NetBSD$	*/

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Christos Zoulas.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by the NetBSD
 *        Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD$");
#endif /* LIBC_SCCS and not lint */

#include "namespace.h"

#include <assert.h>
#include <paths.h>
#include <pwd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

#ifdef __weak_alias
__weak_alias(getpass,_getpass)
#endif

static void sighandler __P((int));
/*
 * This is not re-entrant anyway because of the static buffer
 * so we use static variables to communicate, since there is
 * currently no way to pass data to and from signal handlers.
 */
static int gotsig = -1;

static void
sighandler(n)
	int n;
{
	switch (n) {
	case SIGTSTP:
	case SIGINT:
		gotsig = n;
		return;
	default:
		/* abort? */
		break;
	}
}

char *
getpass(prompt)
	const char *prompt;
{
	int nr;
	char *p;
	int infd, outfd;
	static char buf[_PASSWORD_LEN + 1];
	char *bufp = NULL;
	struct sigaction osaint, osatstp, nsa;
	struct termios nterm, oterm;

	_DIAGASSERT(prompt != NULL);

	gotsig = -1;

	/*
	 * read and write to /dev/tty if possible; else read from
	 * stdin and write to stderr.
	 */
	if ((infd = outfd = open(_PATH_TTY, O_RDWR)) == -1) {
		outfd = STDERR_FILENO;
		infd = STDIN_FILENO;
	}

	if (tcgetattr(infd, &oterm) == -1)
		goto cleanup0;

	nsa.sa_handler = sighandler;
	nsa.sa_flags = 0;
	sigemptyset(&nsa.sa_mask);

	if (sigaction(SIGINT, &nsa, &osaint) == -1)
		goto cleanup0;

	if (sigaction(SIGTSTP, &nsa, &osatstp) == -1)
		goto cleanup1;

	nterm = oterm;
	nterm.c_lflag &= ~(ECHO|ICANON);
	nterm.c_cc[VMIN] = 1;
	nterm.c_cc[VTIME] = 0;

	if (tcsetattr(infd, TCSAFLUSH|TCSASOFT, &nterm) == -1)
		goto cleanup2;


	if (prompt != NULL)
		(void)write(outfd, prompt, strlen(prompt));

	for (p = buf; p < buf + _PASSWORD_LEN; p++) {
		while ((nr = read(infd, p, 1)) == -1 && errno == EINTR) {
			(void)tcsetattr(infd, TCSAFLUSH|TCSASOFT, &oterm);
			(void)sigaction(SIGTSTP, &osatstp, NULL);
			(void)sigaction(SIGINT, &osaint, NULL);
			(void)kill(0, gotsig);
			gotsig = -1;
			(void)sigaction(SIGINT, &nsa, NULL);
			(void)sigaction(SIGTSTP, &nsa, NULL);
			(void)tcsetattr(infd, TCSAFLUSH|TCSASOFT, &nterm);
		}
		if (nr == -1 || *p == '\n' || *p == oterm.c_cc[VEOF])
			break;
		if (*p == oterm.c_cc[VERASE])
			p -= p > buf ? 2 : 1;
		else if (*p == oterm.c_cc[VKILL])
			p = buf - 1;
		else if (*p == oterm.c_cc[VREPRINT] && p >= buf)
			p--;
		/* XXX: we don't handle VWERASE, VLNEXT, VSTART, VSTOP etc. */
	}
	*p = '\0';
	(void)write(outfd, "\n", 1);
	bufp = buf;

	(void)tcsetattr(infd, TCSAFLUSH|TCSASOFT, &oterm);
cleanup2:
	(void)sigaction(SIGTSTP, &osatstp, NULL);
cleanup1:
	(void)sigaction(SIGINT, &osaint, NULL);
cleanup0:
	if (infd == outfd && infd != -1)
		(void)close(infd);
	return(bufp);
}

#ifdef TEST
static void sigtest __P((int));
int main __P((int, char *[]));

static void
sigtest(n)
	int n;
{
	printf("got signal %d\n", n);
}

int
main(argc, argv)
	int argc;
	char *argv[];
{
	struct sigaction sa;
	char *foo;

	foo = getpass("notrap:");
	printf("notrap = %s\n", foo);
	sa.sa_handler = sigtest;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	(void) sigaction(SIGINT, &sa, NULL);
	(void) sigaction(SIGTSTP, &sa, NULL);
	foo = getpass("trap:");
	printf("trap = %s\n", foo);
	return 0;
}
#endif
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: lib-bug-people->kamil
Responsible-Changed-By: kamil@NetBSD.org
Responsible-Changed-When: Sat, 07 Oct 2017 14:39:07 +0200
Responsible-Changed-Why:
Take.


From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, kamil@NetBSD.org, lib-bug-people@netbsd.org, 
	netbsd-bugs@netbsd.org, gnats-admin@netbsd.org
Cc: 
Subject: Re: lib/10955 (libc getpass(3) blocks signals.)
Date: Sat, 7 Oct 2017 09:55:36 -0400

 On Oct 7, 12:39pm, kamil@NetBSD.org (kamil@NetBSD.org) wrote:
 -- Subject: Re: lib/10955 (libc getpass(3) blocks signals.)

 | Synopsis: libc getpass(3) blocks signals.
 | 
 | Responsible-Changed-From-To: lib-bug-people->kamil
 | Responsible-Changed-By: kamil@NetBSD.org
 | Responsible-Changed-When: Sat, 07 Oct 2017 14:39:07 +0200
 | Responsible-Changed-Why:
 | Take.

 Close it... :-)

 christos

State-Changed-From-To: open->closed
State-Changed-By: kamil@NetBSD.org
State-Changed-When: Sat, 07 Oct 2017 16:06:04 +0200
State-Changed-Why:
Closed on request of the originator.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.