This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Updated partial auth patch against CVS


Hi Corinna...

Here is the same patch, combined with Carsons patch. You can apply this 
directly to 2.5.2p2. Please take a look at it for me. It gives the user the 
ability to provide partial authentication with CygWin. In particular, with 
it users can have an authentication sequence like:

publickey (if the server uid matches the logon uid) and
publickey followed by password (if the server uid is different from the 
logon uid)

this gives the security advantage of publickey authentication against 
password cracking, and gets a password to the server to make windows happy. 
And, the above example allows special administrative tasks to avoid 
passwords (for that one special user id in your life).

If anyone else wants to give it a try, let me know if you need any help.

Thanks,

...Karl

>From: "Karl M" <karlm30@hotmail.com>
>To: openssh-unix-dev@mindrot.org
>CC: cygwin@cygwin.com
>Subject: Re: Updated partial auth patch against CVS
>Date: Sat, 05 May 2001 14:17:22 -0700
>
>Hi Carson...
>
>Here is what I have so far. This is a patch based on 2.5.2p2 with your
>patch. So this is a patch on top of your patch. This patch allows
>
>AuthOrder2 publickey:uidmatch,publickey:password
>
>for the CygWin environment. It also highlites a couple of minor things I
>found in your patch. When you have a 2.9p1 patch I will update this.
>
>Thanks,
>
>...Karl
>
>_________________________________________________________________
>Get your FREE download of MSN Explorer at http://explorer.msn.com
><< diffFromCarson252p2patch.txt >>
>--
>Want to unsubscribe from this list?
>Check out: http://cygwin.com/ml/#unsubscribe-simple

_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com
diff -u -r ./auth.c /openssh-2.5.2p2/auth.c
--- ./auth.c	Mon Mar 19 13:15:58 2001
+++ /openssh-2.5.2p2/auth.c	Fri May  4 20:30:52 2001
@@ -185,8 +185,15 @@

	if (authctxt->postponed)
		authmsg = "Postponed";
-	else
-		authmsg = authenticated ? "Accepted" : "Failed";
+	else if (!authenticated) {
+		if (authctxt->partial) {
+			authmsg = "Accepted Partial";
+		} else {
+			authmsg = "Failed";
+		}
+	} else {
+		authmsg = "Accepted";
+	}

	authlog("%s %s for %s%.100s from %.200s port %d%s",
	    authmsg,
diff -u -r ./auth.h /openssh-2.5.2p2/auth.h
--- ./auth.h	Sun Mar  4 20:56:42 2001
+++ /openssh-2.5.2p2/auth.h	Fri May  4 20:30:53 2001
@@ -39,6 +39,7 @@
struct Authctxt {
	int success;
	int postponed;
+        int partial;
	int valid;
	int attempt;
	int failures;
diff -u -r ./auth2.c /openssh-2.5.2p2/auth2.c
--- ./auth2.c	Sun Mar 11 11:01:56 2001
+++ /openssh-2.5.2p2/auth2.c	Sat May  5 13:59:52 2001
@@ -61,6 +61,16 @@
static Authctxt	*x_authctxt = NULL;
static int one = 1;

+typedef struct Authorder Authorder;
+struct Authorder {
+	char *name;
+	Authorder *sub;
+	Authorder *next;
+};
+
+static Authorder *authorder = NULL;
+static Authorder *lastauth = NULL;
+
typedef struct Authmethod Authmethod;
struct Authmethod {
	char	*name;
@@ -78,6 +88,8 @@
Authmethod	*authmethod_lookup(const char *name);
int	user_key_allowed(struct passwd *pw, Key *key);
char	*authmethods_get(void);
+Authmethod	*authmethod_lookup_new(const char *name, Authorder **ao);
+char	*authmethods_get_new(void);

/* auth */
void	userauth_banner(void);
@@ -171,8 +183,11 @@
{
	Authctxt *authctxt = ctxt;
	Authmethod *m = NULL;
+	Authorder *ao = NULL;
	char *user, *service, *method, *style = NULL;
	int authenticated = 0;
+	int r;
+	int tempuid;

	if (authctxt == NULL)
		fatal("input_userauth_request: no authctxt");
@@ -226,7 +241,7 @@
#endif

	/* try to authenticate user */
-	m = authmethod_lookup(method);
+	m = authmethod_lookup_new(method, &ao);
	if (m != NULL) {
		debug2("input_userauth_request: try method %s", method);
		authenticated =	m->userauth(authctxt);
@@ -246,6 +261,37 @@
		authenticated = 0;
#endif /* USE_PAM */

+	authctxt->partial = 0;
+/* Karl-->Carson: We could change this to a while if we want to let 
matchuid
+		  have subauth methods. */
+	if (authenticated && (ao->sub != NULL)) {
+		authctxt->partial = 1;
+		authenticated = 0;
+		lastauth = ao;
+#ifdef HAVE_CYGWIN
+		ao = ao->sub;
+		while (((r = strcmp("matchuid",ao->name)) != 0) && (ao->next != NULL))
+			ao = ao->next;
+		if ((r == 0) && (getuid() == authctxt->pw->pw_uid)) {
+			authctxt->partial = 0;
+			authenticated = 1;
+		}
+#endif
+	}
+
+#ifdef HAVE_CYGWIN
+/* Karl-->Corinna: I have removed the check_nt_calls from everything but
+		   userauth_passwd. I want to make sure that we have a
+		   password if we need it. Is there a better way to do this? */
+	if (authenticated) {
+		tempuid = getuid();
+		setuid(authctxt->pw->pw_uid);
+		if (getuid() != authctxt->pw->pw_uid)
+			authenticated = 0;
+		setuid(tempuid);
+	}
+#endif
+
	/* Log before sending the reply */
	auth_log(authctxt, authenticated, method, " ssh2");

@@ -296,7 +342,6 @@
{
	char *methods;

-	/* XXX todo: check if multiple auth methods are needed */
	if (authenticated == 1) {
#ifdef WITH_AIXAUTHENTICATE
		/* We don't have a pty yet, so just label the line as "ssh" */
@@ -313,12 +358,18 @@
		/* now we can break out */
		authctxt->success = 1;
	} else {
-		if (authctxt->failures++ > AUTH_FAIL_MAX)
-			packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
-		methods = authmethods_get();
+		if (!authctxt->partial) {
+			if (authctxt->failures++ > AUTH_FAIL_MAX)
+				packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+		}
+		methods = authmethods_get_new();
		packet_start(SSH2_MSG_USERAUTH_FAILURE);
		packet_put_cstring(methods);
-		packet_put_char(0);	/* XXX partial success, unused */
+		if (authctxt->partial) {
+			packet_put_char(1); /* Partial Auth */
+		} else {
+			packet_put_char(0);
+		}
		packet_send();
		packet_write_wait();
		xfree(methods);
@@ -328,20 +379,35 @@
int
userauth_none(Authctxt *authctxt)
{
+	Authorder *ao, *ap;
+	int r;
+
	/* disable method "none", only allowed one time */
-	Authmethod *m = authmethod_lookup("none");
-	if (m != NULL)
-		m->enabled = NULL;
+	ao = authorder;
+	ap = NULL;
+	while (((r = strcmp("none", ao->name)) != 0) && (ao->next != NULL)) {
+		ap = ao;
+		ao = ao->next;
+	}
+	if (r == 0) {
+		if (ap == NULL) {
+			authorder = ao->next;
+			xfree(ao->name);
+			/* If none had sub-methods, we leak memory here, but that should never 
happen */
+			xfree(ao);
+		} else {
+			ap->next = ao->next;
+			xfree(ao->name);
+			/* If none had sub-methods, we leak memory here, but that should never 
happen */
+			xfree(ao);
+		}
+	}
	packet_done();
	userauth_banner();

	if (authctxt->valid == 0)
		return(0);

-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(1, authctxt->pw->pw_uid) == 0)
-		return(0);
-#endif
#ifdef USE_PAM
	return auth_pam_password(authctxt->pw, "");
#elif defined(HAVE_OSF_SIA)
@@ -402,10 +468,6 @@
#endif
	xfree(lang);
	xfree(devs);
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
-		return(0);
-#endif
	return authenticated;
}

@@ -508,10 +570,6 @@
	debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
	xfree(pkalg);
	xfree(pkblob);
-#ifdef HAVE_CYGWIN
-	if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
-		return(0);
-#endif
	return authenticated;
}

@@ -557,6 +615,149 @@
	return list;
}

+void authorder_init(void) {
+	char *cp, sep;
+	int i, j, k, r;
+	Authorder *ao, *as;
+
+	/* none is magic */
+	authorder = (Authorder *) xmalloc(sizeof(Authorder));
+	authorder->name = (char *) xmalloc(5);
+	strlcpy(authorder->name, "none", 5);
+	authorder->sub = NULL;
+	authorder->next = NULL;
+
+	sep = ',';
+
+	cp = options.authorder;
+	ao = authorder;
+	while (*cp != NULL) {
+		/* strip leading cruft */
+		i = strspn(cp, ",; 	");
+		cp += i;
+		if (*cp == NULL) {
+			break;
+		}
+		/* find name */
+		i = strcspn(cp, ",: 	");
+		j = strcspn(cp+i, ",:");
+		if (i > 0) {
+			switch(sep) {
+			case ':':
+				if (ao->sub == NULL) {
+					ao->sub = (Authorder *) xmalloc(sizeof(Authorder));
+					as = ao->sub;
+					as->name = NULL;
+					as->sub = NULL;
+					as->next = NULL;
+					r = 1;
+				} else {
+					as = ao->sub;
+/* Karl-->Carson: Needs to be case insensitive for the way servconf.c is 
now. */
+					while ((r = strncasecmp(as->name, cp, i)) != 0) {
+						if (as->next != NULL) {
+							as = as->next;
+						} else {
+							break;
+						}
+					}
+				}
+				if (r != 0) {
+					if (as->name != NULL) {
+						as->next = (Authorder *) xmalloc(sizeof(Authorder));
+						as = as->next;
+					}
+					as->name = (char *) xmalloc(i+1);
+					for (k=0; k<i; k++) {
+						as->name[k] = tolower(cp[k]);
+					}
+					as->name[i] = '\0';
+					as->sub = NULL;
+					as->next = NULL;
+					ao = as;
+				}
+				ao = as;
+				break;
+			case ',':
+				ao = authorder;
+/* Karl-->Carson: Needs to be case insensitive for the way servconf.c is 
now. */
+				while(((r = strncasecmp(ao->name, cp, i)) != 0) && (ao->next != NULL)) 
{
+					ao = ao->next;
+				}
+				if (r != 0) {
+					ao->next = (Authorder *) xmalloc(sizeof(Authorder));
+					ao = ao->next;
+					ao->name = (char *) xmalloc(i+1);
+					for (k=0; k<i; k++) {
+						ao->name[k] = tolower(cp[k]);
+					}
+					ao->name[i] = '\0';
+					ao->sub = NULL;
+					ao->next = NULL;
+				}
+				break;
+			}
+			sep = cp[i+j];
+		}
+		cp += i+j+1;
+	}
+}
+
+char *
+authmethods_get_new(void)
+{
+	Authorder *ao, *as;
+	u_int size = 0;
+	char *list;
+
+	if (authorder == NULL) {
+		authorder_init();
+	}
+
+	if ((lastauth == NULL) || (lastauth->sub == NULL)) {
+		ao = authorder;
+	} else {
+		ao = lastauth->sub;
+	}
+
+	as = ao;
+#ifdef HAVE_CYGWIN
+	if (strcmp("matchuid",as->name) != 0)
+#endif
+	size = strlen(as->name) + 1;
+	while (as->next != NULL) {
+		as = as->next;
+#ifdef HAVE_CYGWIN
+		if (strcmp("matchuid",as->name) != 0)
+#endif
+		size += strlen(as->name) + 1;
+	}
+#ifdef HAVE_CYGWIN
+	if (size == 0)
+		fatal("authmethods_get_new: no authmethods");
+#endif
+/* Karl-->Carson: No need for "size++;" here, is there? */
+	size++;			/* trailing '\0' */
+	list = xmalloc(size);
+#ifdef HAVE_CYGWIN
+	if (strcmp("matchuid",ao->name) == 0)
+		ao = ao->next;
+#endif
+	strlcpy(list, ao->name, size);
+	while(ao->next != NULL) {
+		ao = ao->next;
+#ifdef HAVE_CYGWIN
+		if (strcmp("matchuid",ao->name) != 0) {
+#endif
+		strlcat(list, DELIM, size);
+		strlcat(list, ao->name, size);
+#ifdef HAVE_CYGWIN
+		}
+#endif
+	}
+	return list;
+}
+
Authmethod *
authmethod_lookup(const char *name)
{
@@ -567,6 +768,42 @@
			    *(method->enabled) != 0 &&
			    strcmp(name, method->name) == 0)
				return method;
+	debug2("Unrecognized authentication method name: %s", name ? name : 
"NULL");
+	return NULL;
+}
+
+Authmethod *
+authmethod_lookup_new(const char *name, Authorder **am)
+{
+	Authmethod *method = NULL;
+	Authorder *ao;
+	int r;
+
+	if (name != NULL) {
+		if ((lastauth == NULL) || (lastauth->sub == NULL)) {
+			if (authorder == NULL) {
+				authorder_init();
+			}
+			ao = authorder;
+		} else {
+			ao = lastauth->sub;
+		}
+
+		while(((r = strcmp(name, ao->name)) != 0) && (ao->next != NULL)) {
+			ao = ao->next;
+		}
+
+		if (r != 0) {
+			debug2("Authentication method name \"%s\" not allowed", name);
+			return(NULL);
+		}
+
+		*am = ao;
+
+		for (method = authmethods; method->name != NULL; method++)
+			if (strcmp(name, method->name) == 0)
+				return method;
+	}
	debug2("Unrecognized authentication method name: %s", name ? name : 
"NULL");
	return NULL;
}
diff -u -r ./defines.h /openssh-2.5.2p2/defines.h
--- ./defines.h	Mon Mar 19 17:49:22 2001
+++ /openssh-2.5.2p2/defines.h	Fri May  4 20:49:04 2001
@@ -436,7 +436,7 @@
  * configure.in sets this for a few OS's which are known to have problems
  * but you may need to set it yourself
  */
-/* #define USE_PIPES 1 */
+#define USE_PIPES 1

/**
  ** login recorder definitions
diff -u -r ./openbsd-compat/strmode.c 
/openssh-2.5.2p2/openbsd-compat/strmode.c
--- ./openbsd-compat/strmode.c	Wed Jan 31 12:52:04 2001
+++ /openssh-2.5.2p2/openbsd-compat/strmode.c	Fri May  4 20:34:46 2001
@@ -42,6 +42,15 @@
#include <sys/stat.h>
#include <string.h>

+#ifdef HAVE_CYGWIN
+#undef S_IXUSR
+#undef S_IXGRP
+#undef S_IXOTH
+#define S_IXUSR 0100
+#define S_IXGRP 0010
+#define S_IXOTH 0001
+#endif
+
void
strmode(mode, p)
	register mode_t mode;
diff -u -r ./servconf.c /openssh-2.5.2p2/servconf.c
--- ./servconf.c	Mon Mar  5 16:02:42 2001
+++ /openssh-2.5.2p2/servconf.c	Sat May  5 13:36:09 2001
@@ -96,6 +96,7 @@
	options->max_startups = -1;
	options->banner = NULL;
	options->reverse_mapping_check = -1;
+	options->authorder = NULL;
}

void
@@ -192,6 +193,30 @@
		options->max_startups_begin = options->max_startups;
	if (options->reverse_mapping_check == -1)
		options->reverse_mapping_check = 0;
+	if (options->authorder == NULL) {
+		char *s[2];
+		int size = 0, n = 0, i;
+		if (options->kbd_interactive_authentication) {
+			s[n] = "keyboard-interactive,";
+			size += strlen(s[n]);
+			n++;
+		}
+		if (options->password_authentication) {
+			s[n] = "password,";
+			size += strlen(s[n]);
+		}
+		if (options->pubkey_authentication) {
+			s[n] = "publickey,";
+			size += strlen(s[n]);
+			n++;
+		}
+		size += strlen("none")+1;
+		options->authorder = (char *) xmalloc(size);
+		for (i=0; i<n; i++) {
+			strlcat(options->authorder, s[i], size);
+		}
+		strlcpy(options->authorder, "none", size);
+	}
}

/* Keyword tokens. */
@@ -214,6 +239,7 @@
	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, 
sMaxStartups,
+	sAuthOrder,
	sBanner, sReverseMappingCheck
} ServerOpCodes;

@@ -275,6 +301,7 @@
	{ "maxstartups", sMaxStartups },
	{ "banner", sBanner },
	{ "reversemappingcheck", sReverseMappingCheck },
+	{ "authorder2", sAuthOrder },
	{ NULL, 0 }
};

@@ -729,6 +756,58 @@
		case sBanner:
			charptr = &options->banner;
			goto parse_filename;
+
+		case sAuthOrder:
+			arg = strdelim(&cp);
+/* Karl-->Carson: Should whitespace be removed before processing? */
+/* Karl-->Carson: Perhaps we should just remove whitespace and convert
+		  everything to lowercase to simplify the remaining code
+		  here and in auth2.c? */
+/* Karl-->Carson: These comparisons need to be case insensitive somehow. */
+			if ((strstr(arg,":none") != NULL) || (strstr(arg,"none:") != NULL)){
+				fprintf(stderr, "%s line %d: none may not be or have a subauth 
method\n",
+					filename, linenum);
+				exit(1);
+			}
+#ifdef HAVE_CYGWIN
+/* Karl-->Carson: These comparisons need to be case insensitive somehow. */
+			if ((strncasecmp(arg,"matchuid",8) == 0) || (strstr(arg,",matchuid") != 
NULL) ||
+			    (strstr(arg,"matchuid:") != NULL)){
+				fprintf(stderr, "%s line %d: matchuid must be and not have a subauth 
method\n",
+					filename, linenum);
+				exit(1);
+			}
+#endif
+			{
+				int i, match;
+				char *mycp;
+				mycp = arg;
+				while(((i = strcspn(mycp,",:")) != 0) && (*mycp != NULL)) {
+					match = 0;
+					if (strncasecmp(mycp,"none",i) == 0) {
+						match = 1;
+					} else if (strncasecmp(mycp,"publickey",i) == 0) {
+						match = 1;
+					} else if (strncasecmp(mycp,"password",i) == 0) {
+						match = 1;
+					} else if (strncasecmp(mycp,"keyboard-interactive",i) == 0) {
+						match = 1;
+#ifdef HAVE_CYGWIN
+					} else if (strncasecmp(mycp,"matchuid",i) == 0) {
+						match = 1;
+#endif
+					}
+					if (match == 0) {
+						mycp[i]='\0';
+						fprintf(stderr, "%s line %d: illegal auth method %s",
+							filename, linenum, mycp);
+						exit(1);
+					}
+					mycp += i+1;
+				}
+			}
+			options->authorder = xstrdup(arg);
+			break;

		default:
			fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
diff -u -r ./servconf.h /openssh-2.5.2p2/servconf.h
--- ./servconf.h	Wed Feb 14 18:08:28 2001
+++ /openssh-2.5.2p2/servconf.h	Fri May  4 20:30:53 2001
@@ -112,6 +112,7 @@
	int	max_startups;
	char   *banner;			/* SSH-2 banner message */
	int	reverse_mapping_check;	/* cross-check ip and dns */
+	char   *authorder;		/* Authentication Orders */

}       ServerOptions;
/*


--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]