Index: auth1.c
--- auth1.c.orig	2009-03-08 01:40:28 +0100
+++ auth1.c	2009-10-02 13:10:17 +0200
@@ -40,6 +40,9 @@
 #endif
 #include "monitor_wrap.h"
 #include "buffer.h"
+#ifdef USE_ALIAS
+#include "match.h"
+#endif
 
 /* import */
 extern ServerOptions options;
@@ -384,6 +387,10 @@
 {
 	u_int ulen;
 	char *user, *style = NULL;
+#ifdef USE_ALIAS
+	int i, n;
+	char *cp;
+#endif
 
 	/* Get the name of the user that we wish to log in as. */
 	packet_read_expect(SSH_CMSG_USER);
@@ -395,6 +402,25 @@
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = '\0';
 
+#ifdef USE_ALIAS
+	for (i = 0; i < options.num_alias; i++) {
+		if (match_pattern_list(user, options.alias[i].alias, strlen(options.alias[i].alias), 0) == 1) {
+			if (style != NULL) {
+				n = strlen(options.alias[i].user) + 1 + strlen(style) + 1;
+				cp = xmalloc(n);
+				snprintf(cp, n, "%s:%s", options.alias[i].user, style);
+				style = strchr(cp, ':');
+				*style++ = '\0';
+			}
+			else
+				cp = xstrdup(options.alias[i].user);
+			xfree(user);
+			user = cp;
+			break;
+		}
+	}
+#endif
+
 	authctxt->user = user;
 	authctxt->style = style;
 
Index: auth2.c
--- auth2.c.orig	2009-06-22 08:11:07 +0200
+++ auth2.c	2009-10-02 13:10:17 +0200
@@ -49,6 +49,9 @@
 #include "dispatch.h"
 #include "pathnames.h"
 #include "buffer.h"
+#ifdef USE_ALIAS
+#include "match.h"
+#endif
 
 #ifdef GSSAPI
 #include "ssh-gss.h"
@@ -217,6 +220,10 @@
 	Authmethod *m = NULL;
 	char *user, *service, *method, *style = NULL;
 	int authenticated = 0;
+#ifdef USE_ALIAS
+	int i, n;
+	char *cp;
+#endif
 
 	if (authctxt == NULL)
 		fatal("input_userauth_request: no authctxt");
@@ -230,6 +237,25 @@
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = 0;
 
+#ifdef USE_ALIAS
+	for (i = 0; i < options.num_alias; i++) {
+		if (match_pattern_list(user, options.alias[i].alias, strlen(options.alias[i].alias), 0) == 1) {
+			if (style != NULL) {
+				n = strlen(options.alias[i].user) + 1 + strlen(style) + 1;
+				cp = xmalloc(n);
+				snprintf(cp, n, "%s:%s", options.alias[i].user, style);
+				style = strchr(cp, ':');
+				*style++ = '\0';
+			}
+			else
+				cp = xstrdup(options.alias[i].user);
+			xfree(user);
+			user = cp;
+			break;
+		}
+	}
+#endif
+
 	if (authctxt->attempt++ == 0) {
 		/* setup auth context */
 		authctxt->pw = PRIVSEP(getpwnamallow(user));
Index: servconf.c
--- servconf.c.orig	2009-06-21 12:26:17 +0200
+++ servconf.c	2009-10-02 13:10:17 +0200
@@ -128,6 +128,9 @@
 	options->adm_forced_command = NULL;
 	options->chroot_directory = NULL;
 	options->zero_knowledge_password_authentication = -1;
+#ifdef USE_ALIAS
+ 	options->num_alias = 0;
+#endif
 }
 
 void
@@ -306,6 +309,9 @@
 	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
 	sUsePrivilegeSeparation, sAllowAgentForwarding,
 	sZeroKnowledgePasswordAuthentication,
+#ifdef USE_ALIAS
+	sAlias,
+#endif
 	sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -424,6 +430,9 @@
 	{ "permitopen", sPermitOpen, SSHCFG_ALL },
 	{ "forcecommand", sForceCommand, SSHCFG_ALL },
 	{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+#ifdef USE_ALIAS
+ 	{ "alias", sAlias },
+#endif
 	{ NULL, sBadOption, 0 }
 };
 
@@ -1301,6 +1310,26 @@
 		    arg = strdelim(&cp);
 		break;
 
+#ifdef USE_ALIAS
+	case sAlias:
+		if (options->num_alias >= MAX_ALIAS) {
+			fatal("%s line %d: too many user alias defined.",
+			    filename, linenum);
+		}
+		arg = strdelim(&cp);
+		if (arg == NULL || arg[0] == '\0')
+			fatal("%s line %d: missing user name alias(es).",
+			    filename, linenum);
+		options->alias[options->num_alias].alias = xstrdup(arg);
+		arg = strdelim(&cp);
+		if (arg == NULL || arg[0] == '\0')
+			fatal("%s line %d: missing user name to map alias '%s' to.",
+			    filename, linenum, options->alias[options->num_alias].alias);
+		options->alias[options->num_alias].user = xstrdup(arg);
+		options->num_alias++;
+		break;
+#endif
+
 	case sUnsupported:
 		logit("%s line %d: Unsupported option %s",
 		    filename, linenum, arg);
Index: servconf.h
--- servconf.h.orig	2009-01-28 06:31:23 +0100
+++ servconf.h	2009-10-02 13:10:17 +0200
@@ -151,6 +151,14 @@
 	int	num_permitted_opens;
 
 	char   *chroot_directory;
+#ifdef USE_ALIAS
+#define MAX_ALIAS 256
+	u_int num_alias;
+	struct {
+		char *alias;  /* the alias list to match */
+		char *user;   /* the username to map to */
+	} alias[MAX_ALIAS];
+#endif
 }       ServerOptions;
 
 void	 initialize_server_options(ServerOptions *);
Index: sshd_config.5
--- sshd_config.5.orig	2009-08-28 02:27:08 +0200
+++ sshd_config.5	2009-10-02 13:10:17 +0200
@@ -104,6 +104,15 @@
 Note that disabling agent forwarding does not improve security
 unless users are also denied shell access, as they can always install
 their own forwarders.
+.It Cm Alias
+Specifies an optional mapping of a list of user name aliases onto
+real user names.  The first argument is a comma separated list of
+user name aliases (optionally prefixed with '!' for negation) to
+match. The characters `*' and `?' can be used as wildcards in the
+alias patterns.  The second argument is the real user name onto
+which the aliases are mapped. This allows the use of appealing
+virtual login names (like `anonymous') instead of their physical
+counterparts (like `anoncvs').
 .It Cm AllowGroups
 This keyword can be followed by a list of group name patterns, separated
 by spaces.
