diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
new file mode 100644
index 3b2935c..7236459
*** a/doc/src/sgml/client-auth.sgml
--- b/doc/src/sgml/client-auth.sgml
*************** omicron         bryanh
*** 1097,1102 ****
--- 1097,1132 ----
       
  
       
+       real_realm
+       
+        
+         If set to 0, the domain's SAM-compatible name (also known as the
+         NetBIOS name) is used for the include_realm
+         option. This is the default. If set to 1, the true realm name from
+         the Kerberos user principal name is used. If you used the
+         include_realm option, you can leave this option
+         disabled to maintain compatibility with existing 
+         pg_ident.conf files.
+        
+       
+      
+ 
+      
+       upn_username
+       
+        
+         If this option is enabled along with real_realm,
+         the user name from the Kerberos UPN is used for authentication. If
+         it is disabled (the default), the SAM-compatible user name is used.
+         Note that libpq> uses the SAM-compatible name if no
+         explicit user name is specified. If you use
+         libpq> (e.g. through the ODBC driver), you should
+         leave this option disabled.
+        
+       
+      
+ 
+      
        map
        
         
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
new file mode 100644
index 0131bfd..0f28f54
*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
*************** typedef SECURITY_STATUS
*** 155,160 ****
--- 155,165 ----
  			(WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
  													   PCtxtHandle, void **);
  static int	pg_SSPI_recvauth(Port *port);
+ static int	pg_SSPI_make_upn(char *accountname,
+ 							 size_t accountnamesize,
+ 							 char *domainname,
+ 							 size_t domainnamesize,
+ 							 bool update_accountname);
  #endif
  
  /*----------------------------------------------------------------
*************** static int
*** 1026,1031 ****
--- 1031,1037 ----
  pg_SSPI_recvauth(Port *port)
  {
  	int			mtype;
+ 	int			status;
  	StringInfoData buf;
  	SECURITY_STATUS r;
  	CredHandle	sspicred;
*************** pg_SSPI_recvauth(Port *port)
*** 1261,1266 ****
--- 1267,1281 ----
  
  	free(tokenuser);
  
+ 	if (port->hba->real_realm) {
+ 		status = pg_SSPI_make_upn(accountname, sizeof(accountname),
+ 								  domainname, sizeof(domainname),
+ 								  port->hba->upn_username);
+ 		if (status != STATUS_OK) {
+ 			return status;
+ 		}
+ 	}
+ 
  	/*
  	 * Compare realm/domain if requested. In SSPI, always compare case
  	 * insensitive.
*************** pg_SSPI_recvauth(Port *port)
*** 1296,1301 ****
--- 1311,1407 ----
  	else
  		return check_usermap(port->hba->usermap, port->user_name, accountname, true);
  }
+ 
+ static int	pg_SSPI_make_upn(char *accountname,
+ 							 size_t accountnamesize,
+ 							 char *domainname,
+ 							 size_t domainnamesize,
+ 							 bool update_accountname)
+ {
+ 	char *samname;
+ 	char *upname = NULL;
+ 	char *p = NULL;
+ 	ULONG upnamesize = 0;
+ 	size_t upnamerealmsize;
+ 	BOOLEAN res;
+ 
+ 	/* Build SAM name (DOMAIN\\user), then translate to UPN
+ 	   (user@kerberos.realm). The realm name is returned in
+ 	   lower case, but that is fine because in SSPI auth,
+ 	   string comparisons are always case-insensitive. */
+ 
+ 	samname = psprintf("%s\\%s", domainname, accountname);
+ 	res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
+ 						NULL, &upnamesize);
+ 
+ 	if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER) || upnamesize == 0) {
+ 		pfree(samname);
+ 		ereport(LOG,
+ 				(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
+ 				 errmsg("could not translate name")));
+ 				 return STATUS_ERROR;
+ 	}
+ 
+ 	/* upnamesize includes the NUL. */
+ 	upname = (char*)malloc(upnamesize);
+ 
+ 	if (!upname) {
+ 		pfree(samname);
+ 		ereport(LOG,
+ 				(errcode(ERRCODE_OUT_OF_MEMORY),
+ 				 errmsg("out of memory")));
+ 		return STATUS_ERROR;
+ 	}
+ 
+ 	res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
+ 						upname, &upnamesize);
+ 
+ 	pfree(samname);
+ 	if (res) {
+ 		p = strrchr(upname, '@');
+ 	}
+ 
+ 	if (!res || p == NULL) {
+ 		ereport(LOG,
+ 				(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
+ 				 errmsg("could not translate name")));
+ 				 return STATUS_ERROR;
+ 	}
+ 
+ 	/* Length of realm name after the '@', including the NUL. */
+ 	upnamerealmsize = upnamesize - (p - upname + 1);
+ 
+ 	/* Replace domainname with realm name. */
+ 	if (upnamerealmsize > domainnamesize) {
+ 		free(upname);
+ 		ereport(LOG,
+ 				(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
+ 				 errmsg("realm name too long")));
+ 				 return STATUS_ERROR;
+ 	}
+ 
+ 	/* Length is now safe. */
+ 	strcpy(domainname, p+1);
+ 
+ 	/* Replace account name as well (in case UPN != SAM)? */
+ 	if (update_accountname) {
+ 		if ((p - upname + 1) > accountnamesize) {
+ 			free(upname);
+ 			ereport(LOG,
+ 					(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
+ 					 errmsg("translated account name too long")));
+ 					 return STATUS_ERROR;
+ 		}
+ 
+ 		*p = 0;
+ 		strcpy(accountname, upname);
+ 	}
+ 
+ 	free(upname);
+ 	return STATUS_OK;
+ }
+ 
+ 
  #endif   /* ENABLE_SSPI */
  
  
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
new file mode 100644
index 28f9fb5..f8defab
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
*************** parse_hba_line(List *line, int line_num,
*** 1287,1292 ****
--- 1287,1302 ----
  		parsedline->auth_method == uaSSPI)
  		parsedline->include_realm = true;
  
+ 	/*
+ 	 * For SSPI, include_realm defaults to the SAM-compatible domain
+ 	 * (aka NetBIOS name) and user names instead of the Kerberos
+ 	 * principal name for compatibility.
+ 	 */
+ 	if (parsedline->auth_method == uaSSPI) {
+ 		parsedline->real_realm = false;
+ 		parsedline->upn_username = false;
+ 	}
+ 
  	/* Parse remaining arguments */
  	while ((field = lnext(field)) != NULL)
  	{
*************** parse_hba_auth_opt(char *name, char *val
*** 1570,1575 ****
--- 1580,1603 ----
  		else
  			hbaline->include_realm = false;
  	}
+ 	else if (strcmp(name, "real_realm") == 0)
+ 	{
+ 		if (hbaline->auth_method != uaSSPI)
+ 			INVALID_AUTH_OPTION("real_realm", gettext_noop("sspi"));
+ 		if (strcmp(val, "1") == 0)
+ 			hbaline->real_realm = true;
+ 		else
+ 			hbaline->real_realm = false;
+ 	}
+ 	else if (strcmp(name, "upn_username") == 0)
+ 	{
+ 		if (hbaline->auth_method != uaSSPI)
+ 			INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
+ 		if (strcmp(val, "1") == 0)
+ 			hbaline->upn_username = true;
+ 		else
+ 			hbaline->upn_username = false;
+ 	}
  	else if (strcmp(name, "radiusserver") == 0)
  	{
  		struct addrinfo *gai_result;
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
new file mode 100644
index 68a953a..9e4ad8e
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
*************** typedef struct HbaLine
*** 77,82 ****
--- 77,84 ----
  	bool		clientcert;
  	char	   *krb_realm;
  	bool		include_realm;
+ 	bool		real_realm;
+ 	bool		upn_username;
  	char	   *radiusserver;
  	char	   *radiussecret;
  	char	   *radiusidentifier;