Mail Archives: cygwin/2003/06/08/15:39:24
--=====================_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 -