An old new idea, and a Cygwin patch (was Re: Call for testing: openssh-5.2)

Corinna Vinschen vinschen at redhat.com
Thu Feb 26 03:22:18 EST 2009


On Feb 17 08:11, Damien Miller wrote:
> On Mon, 16 Feb 2009, Corinna Vinschen wrote:
> > On Feb 16 15:32, Damien Miller wrote:
> > > OpenSSH 5.2 is almost ready for release, [...]
> > 
> > Builds and runs fine on Cygwin 1.7.  Since I won't support any new
> > OpenSSH package for Cygwin 1.5, and since Cygwin 1.7 will stop
> > supporting Windows 9x, I'm wondering if it's ok to strip all Windows 9x
> > support, as well as the *really* old Cygwin version considerations from
> > OpenSSH at this point.  It will strip some extra Cygwin-only code from
> > portable SSH.  Or, maybe we should do that right after the 5.2p1 release?
> 
> Yes, we can do this after the release of 5.2p1.

Below is the patch to remove support for Windows 95/98/Me as well
as support for very old versions of Cygwin.  Please apply.

What's still missing in the upstream sources is code which abstracts the
idea of the root user to the idea of a user with certain privileges.
Cygwin/Windows is not the only platform which has the capability to give
finer grained user rights to a user, so that certain types of tasks are
not necessarily run by the root user.  Given that, the hardcoded checks
for uid == 0 don't make sense in many environments.  To reiterate an
idea I'm proposing for quite some time now:

  Instead of checks as
  
    if (getuid() == 0)
      do_foo_bar ();
    else
      EEEEK!
     
   openssh should have checks along the lines of

    if (uid_has_capability (getuid (), CAP_foo_bar))
      do_foo_bar ();
    else
      EEEEK!

The function uid_has_capability() would be quite simple on systems
which don't have fine-grained user rights:

    int
    uid_has_capability (uid_t uid, int capability)
    {
      return uid == 0;
    }

but could be much more elaborate on other platforms like Linux, Solaris,
or Cygwin.  And, again, I'm willing to help with this stuff in terms of
coding.


Corinna


Index: auth-passwd.c
===================================================================
RCS file: /cvs/openssh/auth-passwd.c,v
retrieving revision 1.89
diff -u -p -r1.89 auth-passwd.c
--- auth-passwd.c	26 Oct 2007 04:25:12 -0000	1.89
+++ auth-passwd.c	25 Feb 2009 16:06:53 -0000
@@ -102,7 +102,7 @@ auth_password(Authctxt *authctxt, const 
 	}
 #endif
 #ifdef HAVE_CYGWIN
-	if (is_winnt) {
+	{
 		HANDLE hToken = cygwin_logon_user(pw, password);
 
 		if (hToken == INVALID_HANDLE_VALUE)
Index: auth1.c
===================================================================
RCS file: /cvs/openssh/auth1.c,v
retrieving revision 1.124
diff -u -p -r1.124 auth1.c
--- auth1.c	9 Jul 2008 10:54:05 -0000	1.124
+++ auth1.c	25 Feb 2009 16:06:53 -0000
@@ -318,15 +318,7 @@ do_authloop(Authctxt *authctxt)
 		}
 #endif /* _UNICOS */
 
-#ifdef HAVE_CYGWIN
-		if (authenticated &&
-		    !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,
-		    authctxt->pw)) {
-			packet_disconnect("Authentication rejected for uid %d.",
-			    authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid);
-			authenticated = 0;
-		}
-#else
+#ifndef HAVE_CYGWIN
 		/* Special handling for root */
 		if (authenticated && authctxt->pw->pw_uid == 0 &&
 		    !auth_root_allowed(meth->name)) {
Index: auth2-kbdint.c
===================================================================
RCS file: /cvs/openssh/auth2-kbdint.c,v
retrieving revision 1.7
diff -u -p -r1.7 auth2-kbdint.c
--- auth2-kbdint.c	1 Sep 2006 05:38:36 -0000	1.7
+++ auth2-kbdint.c	25 Feb 2009 16:06:53 -0000
@@ -58,10 +58,6 @@ userauth_kbdint(Authctxt *authctxt)
 
 	xfree(devs);
 	xfree(lang);
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(0, authctxt->pw) == 0)
-		authenticated = 0;
-#endif
 	return authenticated;
 }
 
Index: auth2-none.c
===================================================================
RCS file: /cvs/openssh/auth2-none.c,v
retrieving revision 1.19
diff -u -p -r1.19 auth2-none.c
--- auth2-none.c	2 Jul 2008 12:56:09 -0000	1.19
+++ auth2-none.c	25 Feb 2009 16:06:53 -0000
@@ -61,10 +61,6 @@ userauth_none(Authctxt *authctxt)
 {
 	none_enabled = 0;
 	packet_check_eom();
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(1, authctxt->pw) == 0)
-		return (0);
-#endif
 	if (options.password_authentication)
 		return (PRIVSEP(auth_password(authctxt, "")));
 	return (0);
Index: auth2-passwd.c
===================================================================
RCS file: /cvs/openssh/auth2-passwd.c,v
retrieving revision 1.11
diff -u -p -r1.11 auth2-passwd.c
--- auth2-passwd.c	5 Aug 2006 02:39:39 -0000	1.11
+++ auth2-passwd.c	25 Feb 2009 16:06:53 -0000
@@ -68,10 +68,6 @@ userauth_passwd(Authctxt *authctxt)
 		logit("password change not supported");
 	else if (PRIVSEP(auth_password(authctxt, password)) == 1)
 		authenticated = 1;
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(1, authctxt->pw) == 0)
-		authenticated = 0;
-#endif
 	memset(password, 0, len);
 	xfree(password);
 	return authenticated;
Index: auth2-pubkey.c
===================================================================
RCS file: /cvs/openssh/auth2-pubkey.c,v
retrieving revision 1.20
diff -u -p -r1.20 auth2-pubkey.c
--- auth2-pubkey.c	4 Jul 2008 02:54:25 -0000	1.20
+++ auth2-pubkey.c	25 Feb 2009 16:06:53 -0000
@@ -170,10 +170,6 @@ done:
 		key_free(key);
 	xfree(pkalg);
 	xfree(pkblob);
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(0, authctxt->pw) == 0)
-		authenticated = 0;
-#endif
 	return authenticated;
 }
 
Index: session.c
===================================================================
RCS file: /cvs/openssh/session.c,v
retrieving revision 1.380
diff -u -p -r1.380 session.c
--- session.c	28 Jan 2009 05:29:49 -0000	1.380
+++ session.c	25 Feb 2009 16:06:54 -0000
@@ -571,8 +571,7 @@ do_exec_no_pty(Session *s, const char *c
 	signal(WJSIGNAL, cray_job_termination_handler);
 #endif /* _UNICOS */
 #ifdef HAVE_CYGWIN
-	if (is_winnt)
-		cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
 #endif
 
 	s->pid = pid;
@@ -726,8 +725,7 @@ do_exec_pty(Session *s, const char *comm
 	signal(WJSIGNAL, cray_job_termination_handler);
 #endif /* _UNICOS */
 #ifdef HAVE_CYGWIN
-	if (is_winnt)
-		cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+	cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
 #endif
 
 	s->pid = pid;
@@ -1116,7 +1114,7 @@ do_setup_env(Session *s, const char *she
 	u_int i, envsize;
 	char **env, *laddr;
 	struct passwd *pw = s->pw;
-#ifndef HAVE_LOGIN_CAP
+#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
 	char *path = NULL;
 #endif
 
@@ -1551,9 +1549,6 @@ do_setusercontext(struct passwd *pw)
 #endif
 	}
 
-#ifdef HAVE_CYGWIN
-	if (is_winnt)
-#endif
 	if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
 		fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
 
Index: openbsd-compat/bsd-cygwin_util.c
===================================================================
RCS file: /cvs/openssh/openbsd-compat/bsd-cygwin_util.c,v
retrieving revision 1.20
diff -u -p -r1.20 bsd-cygwin_util.c
--- openbsd-compat/bsd-cygwin_util.c	17 Jul 2008 09:03:49 -0000	1.20
+++ openbsd-compat/bsd-cygwin_util.c	25 Feb 2009 16:06:54 -0000
@@ -39,9 +39,6 @@
 #endif
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/vfs.h>
 
 #include <fcntl.h>
 #include <stdlib.h>
@@ -49,11 +46,6 @@
 #include <windows.h>
 
 #include "xmalloc.h"
-#define is_winnt       (GetVersion() < 0x80000000)
-
-#define ntsec_on(c)	((c) && strstr((c),"ntsec") && !strstr((c),"nontsec"))
-#define ntsec_off(c)	((c) && strstr((c),"nontsec"))
-#define ntea_on(c)	((c) && strstr((c),"ntea") && !strstr((c),"nontea"))
 
 int 
 binary_open(const char *filename, int flags, ...)
@@ -79,126 +71,10 @@ binary_pipe(int fd[2])
 	return (ret);
 }
 
-#define HAS_CREATE_TOKEN 1
-#define HAS_NTSEC_BY_DEFAULT 2
-#define HAS_CREATE_TOKEN_WO_NTSEC 3
-
-static int 
-has_capability(int what)
-{
-	static int inited;
-	static int has_create_token;
-	static int has_ntsec_by_default;
-	static int has_create_token_wo_ntsec;
-
-	/* 
-	 * has_capability() basically calls uname() and checks if
-	 * specific capabilities of Cygwin can be evaluated from that.
-	 * This simplifies the calling functions which only have to ask
-	 * for a capability using has_capability() instead of having
-	 * to figure that out by themselves.
-	 */
-	if (!inited) {
-		struct utsname uts;
-		
-		if (!uname(&uts)) {
-			int major_high = 0, major_low = 0, minor = 0;
-			int api_major_version = 0, api_minor_version = 0;
-			char *c;
-
-			sscanf(uts.release, "%d.%d.%d", &major_high,
-			    &major_low, &minor);
-			if ((c = strchr(uts.release, '(')) != NULL) {
-				sscanf(c + 1, "%d.%d", &api_major_version,
-				    &api_minor_version);
-			}
-			if (major_high > 1 ||
-			    (major_high == 1 && (major_low > 3 ||
-			    (major_low == 3 && minor >= 2))))
-				has_create_token = 1;
-			if (api_major_version > 0 || api_minor_version >= 56)
-				has_ntsec_by_default = 1;
-			if (major_high > 1 ||
-			    (major_high == 1 && major_low >= 5))
-				has_create_token_wo_ntsec = 1;
-			inited = 1;
-		}
-	}
-	switch (what) {
-	case HAS_CREATE_TOKEN:
-		return (has_create_token);
-	case HAS_NTSEC_BY_DEFAULT:
-		return (has_ntsec_by_default);
-	case HAS_CREATE_TOKEN_WO_NTSEC:
-		return (has_create_token_wo_ntsec);
-	}
-	return (0);
-}
-
-int
-check_nt_auth(int pwd_authenticated, struct passwd *pw)
-{
-	/*
-	* 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 doesn't apply to Cygwin versions >= 1.3.2 anymore which
-	* uses the undocumented NtCreateToken() call to create a user
-	* token if the process has the appropriate privileges and if
-	* CYGWIN ntsec setting is on.
-	*/
-	static int has_create_token = -1;
-
-	if (pw == NULL)
-		return 0;
-	if (is_winnt) {
-		if (has_create_token < 0) {
-			char *cygwin = getenv("CYGWIN");
-
-			has_create_token = 0;
-			if (has_capability(HAS_CREATE_TOKEN) &&
-			    (ntsec_on(cygwin) ||
-			    (has_capability(HAS_NTSEC_BY_DEFAULT) &&
-			     !ntsec_off(cygwin)) ||
-			     has_capability(HAS_CREATE_TOKEN_WO_NTSEC)))
-				has_create_token = 1;
-		}
-		if (has_create_token < 1 &&
-		    !pwd_authenticated && geteuid() != pw->pw_uid)
-			return (0);
-	}
-	return (1);
-}
-
 int
 check_ntsec(const char *filename)
 {
 	return (pathconf(filename, _PC_POSIX_PERMISSIONS));
-}
-
-void
-register_9x_service(void)
-{
-        HINSTANCE kerneldll;
-        DWORD (*RegisterServiceProcess)(DWORD, DWORD);
-
-	/* The service register mechanism in 9x/Me is pretty different from
-	 * NT/2K/XP.  In NT/2K/XP we're using a special service starter
-	 * application to register and control sshd as service.  This method
-	 * doesn't play nicely with 9x/Me.  For that reason we register here
-	 * as service when running under 9x/Me.  This function is only called
-	 * by the child sshd when it's going to daemonize.
-	 */
-	if (is_winnt)
-		return;
-	if (!(kerneldll = LoadLibrary("KERNEL32.DLL")))
-		return;
-	if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD))
-		GetProcAddress(kerneldll, "RegisterServiceProcess")))
-		return;
-	RegisterServiceProcess(0, 1);
 }
 
 #define NL(x) x, (sizeof (x) - 1)
Index: openbsd-compat/daemon.c
===================================================================
RCS file: /cvs/openssh/openbsd-compat/daemon.c,v
retrieving revision 1.9
diff -u -p -r1.9 daemon.c
--- openbsd-compat/daemon.c	2 Aug 2006 13:33:55 -0000	1.9
+++ openbsd-compat/daemon.c	25 Feb 2009 16:06:54 -0000
@@ -57,18 +57,8 @@ daemon(int nochdir, int noclose)
 	case -1:
 		return (-1);
 	case 0:
-#ifdef HAVE_CYGWIN
-		register_9x_service();
-#endif
 		break;
 	default:
-#ifdef HAVE_CYGWIN
-		/*
-		 * This sleep avoids a race condition which kills the
-		 * child process if parent is started by a NT/W2K service.
-		 */
-		sleep(1);
-#endif
 		_exit(0);
 	}
 

-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


More information about the openssh-unix-dev mailing list