[PATCH]: Cygwin port of 2.2.0p1

Corinna Vinschen vinschen at cygnus.com
Wed Sep 6 03:35:19 EST 2000


Damien Miller wrote:
> --- There are lots of cases where uid/euid == 0 checks are disabled.
> I assume because Win does not share Unix's root metaphor. Is this
> correct?

This is correct. NT/W2K has lots of special "user rights". Those
user rights can be given to any single user or group of users
explicitely. So, to be a member of the special group "administrators"
does only have a meaning after installation.

> If so, there should be some replacement check to prevent non admin users
> from doing things like setting up port forwards for ports < 1024, etc.

That's impossible. Windows doesn't check that you are some sort
of special user which has the right to use ports < 1024. Everyone
may use that ports. As mentioned above the membership in a user
group doesn't mean much. To get things worse, think of W95/W98
which doesn't know of the concept of different users either.

> --- In auth1.c you have:
> 
> /*
>  * 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.
>  */
> 
> Does this mean the only way to change Window's equivalent of uid is with
> a valid password?

Yes. Without special authentication packages you have no chance
to change the user context without knowing the NT password of that
user.

> The code adjacent to the above comment looks like it will disable
> authentication modes other than password, correct?

No. It doesn't disable other authentications at all. It only disables
non-password authentication _if_ ssh is running in NT/W2K (not 9X/ME)
and _if_ the user running the process is different from the user
trying to login. So you can run sshd under your own account to
login with non-password authentication, nevertheless. But _if_ you
want to change user context (your uid != sshd uid) you are only
able to do that with password auth in NT/W2K. That's the check for.

As I mentioned this may change in future. It's not easy to write
authentication packages for NT/W2K since the documentation is,
uhm, more or less nonexistant and you need special header files 
which aren't part of the standard MS development environment.
However, I'm investigating.

> I can't see anything similar done for protocol v2 though.

You doesn't see that for v2? Wait, just looking through the code...

[time passes]

You're right. Patch related to openssh-SNAP-20000905 attached.

> ---- Also in auth1.c:
> 
> /*
>  * check owner and modes.
>  * This won't work on Windows under all circumstances so we drop
>  * that check for now.
>  */
> 
> How does it fail? I don't want to _remove_ security checks.

FAT filesystems doesn't support that modes.

NTFS does support that modes but NTFS is very complex in that it
doesn't support UNIX modes but access control lists. I have written
a security module for Cygwin called "ntsec" which allows a mapping
between  POSIX and NTFS permissions but it's users choice to use
it and it's inside of the Cygwin subsystem so I can't rely on that
nor can I change the setting from inside a running application.

I didn't want to flood the OpenSSH code with special Win32 code for
checking file systems and getting/setting access control lists.

Hmmm, I _could_ check for the setting of "ntsec" and, if it's set,
remain the aforementioned security check active....

[more time passes]

Ok. It's also in the attached patch. A bit more than I thought
but it's well commented (cygwin_util.c function `check_ntsec').

> --- In session.c you copy the parent's whole environment to the child.
> Is there any way to limit this to specific variables, or (better still)
> initialise them from scratch?

Hmmmm. Windows uses dozens of special env vars. I _could_ figure
out which one to use and which one to drop but it wouldn't make
the code really nicer...
However, I will note that for a later patch.

> I have made a snapshot with your changes merged + a couple of others
> picked up over the last few days.
> 
> http://www.mindrot.org/misc/openssh/openssh-SNAP-20000905.tar.gz
> 
> -d

Thanks :)

Now to the attached patch. I have created a new function `check_nt_auth'
in cygwin_util.c which is called from auth1.c and auth2.c. I would like
to put the `packet_disconnect' call into cygwin_util.c as well but
unfortunately this requires changing ssh-add.c so that `int IPv4orv6'
is defined :-(
The new function `check_ntsec' checks if a later file security check
makes sense.
In `binary_pipe' I forgot a `return' statement.

ChangeLog:
==========
 - auth1.c: Change check for password authentication under Windows
            NT/W2K. Call `check_nt_auth' now.
 - auth2.c: Add check for password authentication under Windows NT/W2K
            by calling `check_nt_auth'.
 - authfile.c: Change checking file permissions for Cygwin by calling
            `check_ntsec' now.
 - cygwin_util.c: New function check_nt_auth().
            New function check_ntsec().
            Add missing return statement in binary_pipe().

Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                        mailto:cygwin at sources.redhat.com
Red Hat, Inc.
mailto:vinschen at cygnus.com
-------------- next part --------------
Index: auth1.c
===================================================================
RCS file: /src/cvsroot//openssh-20000905/auth1.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 auth1.c
--- auth1.c	2000/09/05 11:23:12	1.1.1.1
+++ auth1.c	2000/09/05 12:45:59
@@ -23,11 +23,6 @@ RCSID("$OpenBSD: auth1.c,v 1.3 2000/08/2
 # include <siad.h>
 #endif
 
-#ifdef HAVE_CYGWIN
-#include <windows.h>
-#define is_winnt       (GetVersion() < 0x80000000)
-#endif
-
 /* import */
 extern ServerOptions options;
 extern char *forced_command;
@@ -377,16 +372,8 @@ do_authloop(struct passwd * pw)
 		}
 
 #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;
Index: auth2.c
===================================================================
RCS file: /src/cvsroot//openssh-20000905/auth2.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 auth2.c
--- auth2.c	2000/09/05 11:23:12	1.1.1.1
+++ auth2.c	2000/09/05 12:45:29
@@ -186,6 +186,15 @@ input_userauth_request(int type, int ple
 			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",
@@ -193,8 +202,8 @@ input_userauth_request(int type, int ple
 	}
 
 #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 */
Index: authfile.c
===================================================================
RCS file: /src/cvsroot//openssh-20000905/authfile.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 authfile.c
--- authfile.c	2000/09/05 11:23:12	1.1.1.1
+++ authfile.c	2000/09/05 15:22:08
@@ -457,12 +457,10 @@ load_private_key(const char *filename, c
 	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) {
@@ -475,7 +473,6 @@ load_private_key(const char *filename, c
 		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) {
Index: cygwin_util.c
===================================================================
RCS file: /src/cvsroot//openssh-20000905/cygwin_util.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 cygwin_util.c
--- cygwin_util.c	2000/09/05 11:23:14	1.1.1.1
+++ cygwin_util.c	2000/09/05 16:20:09
@@ -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 @@ int binary_pipe(int fd[2])
                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


More information about the openssh-unix-dev mailing list