- (djm) Update CygWin support from Corinna Vinschen <vinschen@cygnus.com>
diff --git a/ChangeLog b/ChangeLog
index 507469a..b298318 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,5 @@
 20000916
+ - (djm) Update CygWin support from Corinna Vinschen <vinschen@cygnus.com>
  - (djm) Use a real struct sockaddr inside the fake struct sockaddr_storage.
    Patch from Larry Jones <larry.jones@sdrc.com>
  - (djm) Add Steve VanDevender's <stevev@darkwing.uoregon.edu> PAM 
diff --git a/auth1.c b/auth1.c
index 43faa67..99639b5 100644
--- a/auth1.c
+++ b/auth1.c
@@ -29,11 +29,6 @@
 # include <siad.h>
 #endif
 
-#ifdef HAVE_CYGWIN
-#include <windows.h>
-#define is_winnt       (GetVersion() < 0x80000000)
-#endif
-
 /* import */
 extern ServerOptions options;
 extern char *forced_command;
@@ -383,16 +378,8 @@
 		}
 
 #ifdef HAVE_CYGWIN
-		/*
-		 * The only authentication which is able to change the user
-		 * context on NT systems is the password authentication. So
-		 * we deny all requsts for changing the user context if another
-		 * authentication method is used.
-		 * This may change in future when a special openssh
-		 * subauthentication package is available.
-		 */
-		if (is_winnt && type != SSH_CMSG_AUTH_PASSWORD &&
-		    authenticated && geteuid() != pw->pw_uid) {
+		if (authenticated &&
+		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
 			packet_disconnect("Authentication rejected for uid %d.",
 					  (int) pw->pw_uid);
 			authenticated = 0;
diff --git a/auth2.c b/auth2.c
index 804afd8..8b0a4bc 100644
--- a/auth2.c
+++ b/auth2.c
@@ -182,6 +182,15 @@
 			authenticated =	ssh2_auth_pubkey(pw, service);
 		}
 	}
+
+#ifdef HAVE_CYGWIN
+	if (authenticated && !check_nt_auth(strcmp(method, "password") == 0, pw->pw_uid)) {
+		packet_disconnect("Authentication rejected for uid %d.",
+				  (int) pw->pw_uid);
+		authenticated = 0;
+	}
+#endif
+
 	if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
 		authenticated = 0;
 		log("ROOT LOGIN REFUSED FROM %.200s",
@@ -189,8 +198,8 @@
 	}
 
 #ifdef USE_PAM
-		if (authenticated && !do_pam_account(pw->pw_name, NULL))
-			authenticated = 0;
+	if (authenticated && !do_pam_account(pw->pw_name, NULL))
+		authenticated = 0;
 #endif /* USE_PAM */
 
 	/* Raise logging level */
diff --git a/authfile.c b/authfile.c
index 0a5bae9..66bdc0e 100644
--- a/authfile.c
+++ b/authfile.c
@@ -479,12 +479,10 @@
 	if (fd < 0)
 		return 0;
 
-#ifndef HAVE_CYGWIN
-	/*
-	 * check owner and modes.
-	 * This won't work on Windows under all circumstances so we drop
-	 * that check for now.
-	 */
+	/* check owner and modes.  */
+#ifdef HAVE_CYGWIN
+        if (check_ntsec(filename))
+#endif
 	if (fstat(fd, &st) < 0 ||
 	    (st.st_uid != 0 && st.st_uid != getuid()) ||
 	    (st.st_mode & 077) != 0) {
@@ -497,7 +495,6 @@
 		error("It is recommended that your private key files are NOT accessible by others.");
 		return 0;
 	}
-#endif
 	switch (key->type) {
 	case KEY_RSA:
 		if (key->rsa->e != NULL) {
diff --git a/cygwin_util.c b/cygwin_util.c
index 13bd663..88748c4 100644
--- a/cygwin_util.c
+++ b/cygwin_util.c
@@ -18,6 +18,10 @@
 #ifdef HAVE_CYGWIN
 #include <fcntl.h>
 #include <io.h>
+#include <stdlib.h>
+#include <sys/vfs.h>
+#include <windows.h>
+#define is_winnt       (GetVersion() < 0x80000000)
 
 int binary_open(const char *filename, int flags, mode_t mode)
 {
@@ -31,5 +35,67 @@
                setmode (fd[0], O_BINARY);
                setmode (fd[1], O_BINARY);
        }
+       return ret;
+}
+
+int check_nt_auth (int pwd_authenticated, uid_t uid)
+{
+	/*
+	 * The only authentication which is able to change the user
+	 * context on NT systems is the password authentication. So
+	 * we deny all requsts for changing the user context if another
+	 * authentication method is used.
+	 * This may change in future when a special openssh
+	 * subauthentication package is available.
+	 */
+	if (is_winnt && !pwd_authenticated && geteuid() != uid)
+		return 0;
+	return 1;
+}
+
+int check_ntsec (const char *filename)
+{
+	char *cygwin;
+	int allow_ntea = 0;
+	int allow_ntsec = 0;
+	struct statfs fsstat;
+
+	/* Windows 95/98/ME don't support file system security at all. */
+	if (!is_winnt)
+		return 0;
+
+	/* Evaluate current CYGWIN settings. */
+	if ((cygwin = getenv("CYGWIN")) != NULL) {
+		if (strstr(cygwin, "ntea") && !strstr(cygwin, "nontea"))
+			allow_ntea = 1;
+		if (strstr(cygwin, "ntsec") && !strstr(cygwin, "nontsec"))
+			allow_ntsec = 1;
+	}
+
+	/*
+	 * `ntea' is an emulation of POSIX attributes. It doesn't support
+	 * real file level security as ntsec on NTFS file systems does
+	 * but it supports FAT filesystems. `ntea' is minimum requirement
+	 * for security checks.
+	 */
+	if (allow_ntea)
+		return 1;
+
+	/*
+	 * Retrieve file system flags. In Cygwin, file system flags are
+	 * copied to f_type which has no meaning in Win32 itself.
+	 */
+	if (statfs(filename, &fsstat))
+		return 1;
+
+	/*
+	 * Only file systems supporting ACLs are able to set permissions.
+	 * `ntsec' is the setting in Cygwin which switches using of NTFS
+	 * ACLs to support POSIX permissions on files.
+	 */
+	if (fsstat.f_type & FS_PERSISTENT_ACLS)
+		return allow_ntsec;
+
+	return 0;
 }
 #endif