delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2003/06/08/15:39:24

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
Message-Id: <3.0.5.32.20030608153754.0080fdb0@incoming.verizon.net>
X-Sender: vze1u1tg AT incoming DOT verizon DOT net
Date: Sun, 08 Jun 2003 15:37:54 -0400
To: cygwin AT cygwin DOT com, Takashi Yano <takashi DOT yano AT nifty DOT ne DOT jp>
From: "Pierre A. Humblet" <Pierre DOT Humblet AT ieee DOT org>
Subject: Re: Problems on accessing Windows network resources.
In-Reply-To: <Pine.GSO.4.44.0306081450130.25752-100000@slinky.cs.nyu.edu
>
References: <001401c32dd7$dc721b30$2000a8c0 AT kappy>
Mime-Version: 1.0

--=====================_1055115474==_
Content-Type: text/plain; charset="us-ascii"

At 03:09 PM 6/8/2003 -0400, Igor Pechtchanski wrote:
>Takashi,
>
>If you log in without a password: according to the second paragraph of
><http://cygwin.com/cygwin-ug-net/ntsec.html#NTSEC-RELEASE1.3.3>, you
>cannot access network shares that require authentication from a
>passwordless login session.  There is no way to resolve this.  However,
>you should be able to authenticate using the "net use" command with a
>"/user" flag.
>
>The only change between login-1.7-1 and login-1.8-1 was that it switches
>the effective UID (user context) back to the privileged (system) account
>to access utmp (and then restores to the user's UID).  It may be that this
>happens too early, or that switching the UID back and forth affects the
>process's ability to access network shares.  A small testcase (the exact
>instructions on how to reproduce this) would be helpful.  Corinna or
>Pierre might give more insight here.

Coincidentally I was just looking at that. A side effect of switching to 
the system account is that the user access token obtained with a password 
is lost. A new password-less user token is then generated, but it doesn't 
allow as much access. I expect this problem to be fixed within a few days.

Actually I am attaching what should be a fix, but it's only tested on 
WinME. Feedback welcome. Compile as follows and mv the .exe to /bin
gcc login.c -o login -l crypt

Pierre

--=====================_1055115474==_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="login.c"

/*
 * Copyright (c) 1980, 1987, 1988 The Regents of the University of=
 California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =3D
"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of=
 California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] =3D "@(#)login.c	5.32.1.1 (Berkeley) 1/28/89, 1.7-1=
 (Cygwin) 11/14/2002";
#endif /* not lint */

/*
 * login [ name ]
 * login -h hostname	(for telnetd, etc.)
 * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
 */

#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/termios.h>

#include <utmp.h>
#include <signal.h>
#include <lastlog.h>
#include <errno.h>
#include <syslog.h>
#include <grp.h>
#include <pwd.h>
#include <setjmp.h>
#include <stdio.h>
#include <strings.h>

#define	TTYGRPNAME	"tty"		/* name of group to own ttys=
 */

#define=
	MOTDFILE=
	"/etc/motd"
#define=
	MAILDIR=
	=
	"/usr/spool/mail"
#define	NOLOGIN		"/etc/nologin"
#define	HUSHLOGIN	".hushlogin"
#ifdef=
 __CYGWIN__
#define=
	LASTLOG=
	=
	"/var/log/lastlog"
#else
#define	LASTLOG		"/usr/adm/lastlog"
#endif
#define	BSHELL		"/bin/sh"

#ifdef __CYGWIN__
#include <windows.h>
#include <sys/cygwin.h>
#define is_winnt        (GetVersion() < 0x80000000)
#endif

#ifdef __CYGWIN__
#define ROOT_UID	18		// system
#else
#define ROOT_UID	0
#endif

/*
 * This bounds the time given to login.  Not a define so it can
 * be patched on machines where it's too small.
 */
int	timeout =3D 300;

struct	passwd *pwd;
int	failures;
char	term[64], *hostname, *username, *tty;

main(argc, argv)
	int argc;
	char **argv;
{
	extern int errno, optind;
	extern char *optarg, **environ;
	struct group *gr;
	register int ch;
	register char *p;
	int ask, fflag, hflag, pflag, cnt;
	int quietlog, passwd_req, ioctlval;
#ifdef __CYGWIN__
	int priv_uid;
	int priv_gid;
#endif
	void timedout();
	char *domain, *salt, *envinit[1], *ttyn, *pp;
	char tbuf[MAXPATHLEN + 2];
	char *ttyname(), *crypt(), *getpass();
	time_t time();
	off_t lseek();

	(void)signal(SIGALRM,=
 timedout);
	(void)alarm((u_int)timeout);
	(void)signal(SIGQUIT, SIG_IGN);
	(void)signal(SIGINT, SIG_IGN);

	/*
	 * -p is used by getty to tell login not to destroy the environment
 	 * -f is used to skip a second login authentication 
	 * -h is used by other servers to pass the name of the remote
	 *    host to login so that it may be placed in utmp and wtmp
	 */
	(void)gethostname(tbuf, sizeof(tbuf));
	domain =3D index(tbuf, '.');

	fflag =3D hflag =3D pflag =3D 0;
	passwd_req =3D 1;
	while ((ch =3D getopt(argc, argv, "fh:p")) !=3D EOF)
		switch (ch) {
		case 'f':
			fflag =3D 1;
			break;
		case 'h':
#ifndef __CYGWIN__
			if (getuid()) {
				fprintf(stderr,
				    "login: -h for super-user=
 only.\n");
				exit(1);
			}
#endif
			hflag =3D 1;
			if (domain && (p =3D index(optarg, '.')) &&
			    strcasecmp(p, domain) =3D=3D 0)
				*p =3D 0;
			hostname =3D optarg;
			break;
		case 'p':
			pflag =3D 1;
			break;
		case '?':
		default:
			fprintf(stderr, "usage: login [-fp] [username]\n");
			exit(1);
		}
	argc -=3D optind;
	argv +=3D optind;
	if (*argv) {
		username =3D *argv;
		ask =3D 0;
	} else
		ask =3D 1;

	for (cnt =3D getdtablesize(); cnt > 2; cnt--)
		close(cnt);

	ttyn =3D ttyname(0);
	if (ttyn =3D=3D NULL || *ttyn =3D=3D '\0')
		ttyn =3D "/dev/tty??";
	if (tty =3D rindex(ttyn, '/'))
		++tty;
	else
		tty =3D ttyn;

	openlog("login", LOG_ODELAY, LOG_AUTH);

	for (cnt =3D 0;; ask =3D 1) {
#ifndef __CYGWIN__
		ioctlval =3D 0;
		(void)ioctl(0, TIOCSETD, &ioctlval);
#endif
		if (ask) {
			fflag =3D 0;
			getloginname();
		}
		/*
		 * Note if trying multiple user names;
		 * log failures for previous user name,
		 * but don't bother logging one failure
		 * for nonexistent name (mistyped username).
		 */
		if (failures && strcmp(tbuf, username)) {
			if (failures > (pwd ? 0 : 1))
				badlogin(tbuf);
			failures =3D 0;
		}
		(void)strcpy(tbuf, username);
		if (pwd =3D getpwnam(username))
			salt =3D pwd->pw_passwd;
		else
			salt =3D "xx";
		/* if user not super-user, check for disabled logins */
		if (pwd =3D=3D NULL || pwd->pw_uid)
			checknologin();

		/*
		 * Disallow automatic login to root; if not invoked by
		 * root, disallow if the uid's differ.
		 */
		if (fflag && pwd) {
			int uid =3D getuid();

			passwd_req =3D pwd->pw_uid =3D=3D ROOT_UID ||
			    (uid !=3D ROOT_UID && uid !=3D pwd->pw_uid);
		}

		/*
		 * If no pre-authentication and a password exists
		 * for this user, prompt for one and verify it.
		 */
		if (!passwd_req || (pwd && !*pwd->pw_passwd))
			break;

		pp =3D getpass("Password:");
#ifdef __CYGWIN__
                if (is_winnt) {
                        HANDLE hToken =3D cygwin_logon_user (pwd, pp);
                        if (hToken !=3D INVALID_HANDLE_VALUE) {
                                cygwin_set_impersonation_token (hToken);
                                break;
                        }
                } else
#endif
                {
		        p =3D crypt(pp, salt);
                        if (pwd && !strcmp(p, pwd->pw_passwd))
                                break;
                }
		(void) bzero(pp, strlen(pp));

		printf("Login incorrect\n");
		failures++;
		/* we allow 10 tries, but after 3 we start backing off */
		if (++cnt > 3) {
			if (cnt >=3D 10) {
				badlogin(username);
#ifndef __CYGWIN__
				(void)ioctl(0, TIOCHPCL, (struct sgttyb=
 *)NULL);
#endif
				sleepexit(1);
			}
			sleep((u_int)((cnt - 3) * 5));
		}
	}

	/* committed to login -- turn off timeout */
	(void)alarm((u_int)0);
	/*
	 * If valid so far and root is logging in, see if root logins on
	 * this terminal are permitted.
	 */
#ifdef __CYGWIN__
	priv_gid =3D getegid();
	setegid(pwd->pw_gid);
	/* Unfortunately we have to make sure that the user is already
	   the right one to chmod to its home dir on Windows. */
	priv_uid =3D geteuid();
        if (seteuid(pwd->pw_uid)) {
		printf("Switching to user %s failed!\n",=
 username);
		sleep(1);
		exit(0);
	}
#endif
	if (chdir(pwd->pw_dir) < 0) {
		printf("No directory %s!\n", pwd->pw_dir);
		if (chdir("/"))
			exit(0);
		pwd->pw_dir =3D "/";
		printf("Logging in with home =3D \"/\".\n");
	}
	/* nothing else left to fail -- really log in */
#ifdef __CYGWIN__
	/* But we have to revert to the privileged user to access utmp. */
	setegid (priv_gid);
	seteuid (priv_uid);
#endif
	{
		struct utmp utmp;

		bzero((char *)&utmp,=
 sizeof(utmp));
		(void)time(&utmp.ut_time);
		strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
		if (hostname)
			strncpy(utmp.ut_host, hostname,=
 sizeof(utmp.ut_host));
		strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
#ifdef __CYGWIN__
		/* Cygwin has the Linux fields in utmp as well. */
		{
		  int len =3D strlen(tty) - sizeof(utmp.ut_id);
		  if (len > 0)
		    tty +=3D len;
		  strncpy(utmp.ut_id, tty, sizeof(utmp.ut_id));
		  if (len > 0)
		    tty -=3D len;
		  utmp.ut_pid =3D getpid();
		}
#endif
		utmp.ut_type =3D USER_PROCESS;
		login(&utmp);
	}
	setgid(pwd->pw_gid);
        setuid(pwd->pw_uid);

	quietlog =3D access(HUSHLOGIN, F_OK) =3D=3D 0;
	dolastlog(quietlog);

#if 0
	if (!hflag) {					/* XXX */
		static struct winsize win =3D { 0, 0/*, 0, 0*/ };

		(void)ioctl(0, TIOCSWINSZ, &win);
	}
#endif

#ifndef __CYGWIN__
	initgroups(username, pwd->pw_gid);
#endif

	if (*pwd->pw_shell =3D=3D '\0')
		pwd->pw_shell =3D BSHELL;

	/* destroy environment unless user has requested preservation */
#ifndef __CYGWIN__
	if (!pflag)
		environ =3D envinit;
#endif
	(void)setenv("HOME", pwd->pw_dir, 1);
	(void)setenv("SHELL", pwd->pw_shell, 1);
#ifndef __CYGWIN__
	(void)setenv("TERM", term, 0);
#endif
	(void)setenv("USER", pwd->pw_name, 1);
	(void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0);

	if (tty[sizeof("tty")-1] =3D=3D 'd')
		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
	if (pwd->pw_uid =3D=3D 0)
		if (hostname)
			syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s",
			    tty, hostname);
		else
			syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty);

	if (!quietlog) {
		struct stat st;

		motd();
		(void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name);
		if (stat(tbuf, &st) =3D=3D 0 && st.st_size !=3D 0)
			printf("You have %smail.\n",
			    (st.st_mtime > st.st_atime) ? "new " :=
 "");
	}

	(void)signal(SIGALRM, SIG_DFL);
	(void)signal(SIGQUIT, SIG_DFL);
	(void)signal(SIGINT, SIG_DFL);
	(void)signal(SIGTSTP, SIG_IGN);

	tbuf[0] =3D '-';
	strcpy(tbuf + 1, (p =3D rindex(pwd->pw_shell, '/')) ?
	    p + 1 : pwd->pw_shell);
        execlp(pwd->pw_shell, tbuf, 0);
	fprintf(stderr, "login: no shell:=
 ");
	perror(pwd->pw_shell);
	exit(0);
}

getloginname()
{
	register int ch;
	register char *p;
	static char nbuf[UT_NAMESIZE + 1];

	for (;;) {
		printf("login: ");
		for (p =3D nbuf; (ch =3D getchar()) !=3D '\n'; ) {
			if (ch =3D=3D EOF) {
				badlogin(username);
				exit(0);
			}
			if (p < nbuf + UT_NAMESIZE)
				*p++ =3D ch;
		}
		if (p > nbuf)
			if (nbuf[0] =3D=3D '-')
				fprintf(stderr,
				    "login names may not start with '-'.\n");
			else {
				*p =3D '\0';
				username =3D nbuf;
				break;
			}
	}
}

timedout()
{
	fprintf(stderr, "Login timed out after %d seconds\n",=
 timeout);
	exit(0);
}

jmp_buf motdinterrupt;

motd()
{
	register int fd, nchars;
	void (*oldint)(), sigint();
	char tbuf[8192];

	if ((fd =3D open(MOTDFILE, O_RDONLY, 0)) < 0)
		return;
	oldint =3D signal(SIGINT, sigint);
	if (setjmp(motdinterrupt) =3D=3D 0)
		while ((nchars =3D read(fd, tbuf, sizeof(tbuf))) >=
 0)
			(void)write(fileno(stdout), tbuf, nchars);
	(void)signal(SIGINT,=
 oldint);
	(void)close(fd);
}

sigint()
{
	longjmp(motdinterrupt, 1);
}

checknologin()
{
	register int fd, nchars;
	char tbuf[8192];

	if ((fd =3D open(NOLOGIN, O_RDONLY, 0)) >=3D 0) {
		while ((nchars =3D read(fd, tbuf, sizeof(tbuf))) >=
 0)
			(void)write(fileno(stdout), tbuf,=
 nchars);
		sleepexit(0);
	}
}

dolastlog(quiet)
	int quiet;
{
	struct lastlog ll;
	int fd;

	if ((fd =3D open(LASTLOG, O_RDWR, 0)) >=3D 0) {
		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
		if (!quiet) {
			if (read(fd, (char *)&ll, sizeof(ll)) =3D=3D sizeof(ll) &&
			    ll.ll_time !=3D 0) {
				printf("Last login: %.*s ",
				    24-5, (char *)ctime(&ll.ll_time));
				if (*ll.ll_host !=3D '\0')
					printf("from %.*s\n",
					    sizeof(ll.ll_host), ll.ll_host);
				else
					printf("on %.*s\n",
					    sizeof(ll.ll_line), ll.ll_line);
			}
			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll),=
 L_SET);
		}
		bzero((char *)&ll,=
 sizeof(ll));
		(void)time(&ll.ll_time);
		strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
		if (hostname)
			strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
		(void)write(fd, (char *)&ll,=
 sizeof(ll));
		(void)close(fd);
	}
}

badlogin(name)
	char *name;
{
	if (failures =3D=3D 0)
		return;
	if (hostname)
		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s",
		    failures, failures > 1 ? "S" : "", hostname,=
 name);
	else
		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s",
		    failures, failures > 1 ? "S" : "", tty, name);
}


getstr(buf, cnt, err)
	char *buf, *err;
	int cnt;
{
	char ch;

	do {
		if (read(0, &ch, sizeof(ch)) !=3D sizeof(ch))
			exit(1);
		if (--cnt < 0) {
			fprintf(stderr, "%s too long\r\n", err);
			sleepexit(1);
		}
		*buf++ =3D ch;
	} while (ch);
}

sleepexit(eval)
	int eval;
{
	sleep((u_int)5);
	exit(eval);
}



--=====================_1055115474==_
Content-Type: text/plain; charset=us-ascii

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/
--=====================_1055115474==_--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019