*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
***************
*** 126,134 **** char	   *pg_krb_realm = NULL;
   * MIT Kerberos authentication system - protocol version 5
   *----------------------------------------------------------------
   */
- static int pg_krb5_recvauth(Port *port);
- 
  #ifdef KRB5
  
  #include <krb5.h>
  /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
--- 126,133 ----
   * MIT Kerberos authentication system - protocol version 5
   *----------------------------------------------------------------
   */
  #ifdef KRB5
+ static int pg_krb5_recvauth(Port *port);
  
  #include <krb5.h>
  /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
***************
*** 150,163 **** static krb5_principal pg_krb5_server;
   * GSSAPI Authentication
   *----------------------------------------------------------------
   */
- static int pg_GSS_recvauth(Port *port);
- 
  #ifdef ENABLE_GSS
  #if defined(HAVE_GSSAPI_H)
  #include <gssapi.h>
  #else
  #include <gssapi/gssapi.h>
  #endif
  #endif /* ENABLE_GSS */
  
  
--- 149,162 ----
   * GSSAPI Authentication
   *----------------------------------------------------------------
   */
  #ifdef ENABLE_GSS
  #if defined(HAVE_GSSAPI_H)
  #include <gssapi.h>
  #else
  #include <gssapi/gssapi.h>
  #endif
+ 
+ static int pg_GSS_recvauth(Port *port);
  #endif /* ENABLE_GSS */
  
  
***************
*** 165,176 **** static int pg_GSS_recvauth(Port *port);
   * SSPI Authentication
   *----------------------------------------------------------------
   */
- static int pg_SSPI_recvauth(Port *port);
- 
  #ifdef ENABLE_SSPI
  typedef		SECURITY_STATUS
  			(WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
  													   PCtxtHandle, void **);
  #endif
  
  
--- 164,174 ----
   * SSPI Authentication
   *----------------------------------------------------------------
   */
  #ifdef ENABLE_SSPI
  typedef		SECURITY_STATUS
  			(WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
  													   PCtxtHandle, void **);
+ static int pg_SSPI_recvauth(Port *port);
  #endif
  
  
***************
*** 236,251 **** auth_failed(Port *port, int status)
  		case uaPassword:
  			errstr = gettext_noop("password authentication failed for user \"%s\"");
  			break;
- #ifdef USE_PAM
  		case uaPAM:
  			errstr = gettext_noop("PAM authentication failed for user \"%s\"");
  			break;
- #endif   /* USE_PAM */
- #ifdef USE_LDAP
  		case uaLDAP:
  			errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
  			break;
- #endif   /* USE_LDAP */
  		default:
  			errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
  			break;
--- 234,245 ----
***************
*** 316,333 **** ClientAuthentication(Port *port)
--- 310,339 ----
  			}
  
  		case uaKrb5:
+ #ifdef KRB5
  			sendAuthRequest(port, AUTH_REQ_KRB5);
  			status = pg_krb5_recvauth(port);
+ #else
+ 			Assert(false);
+ #endif
  			break;
  
  		case uaGSS:
+ #ifdef ENABLE_GSS
  			sendAuthRequest(port, AUTH_REQ_GSS);
  			status = pg_GSS_recvauth(port);
+ #else
+ 			Assert(false);
+ #endif
  			break;
  
  		case uaSSPI:
+ #ifdef ENABLE_SSPI
  			sendAuthRequest(port, AUTH_REQ_SSPI);
  			status = pg_SSPI_recvauth(port);
+ #else
+ 			Assert(false);
+ #endif
  			break;
  
  		case uaIdent:
***************
*** 377,393 **** ClientAuthentication(Port *port)
  			status = recv_and_check_password_packet(port);
  			break;
  
- #ifdef USE_PAM
  		case uaPAM:
  			pam_port_cludge = port;
  			status = CheckPAMAuth(port, port->user_name, "");
  			break;
  #endif   /* USE_PAM */
  
- #ifdef USE_LDAP
  		case uaLDAP:
  			status = CheckLDAPAuth(port);
  			break;
  #endif
  
  		case uaTrust:
--- 383,403 ----
  			status = recv_and_check_password_packet(port);
  			break;
  
  		case uaPAM:
+ #ifdef USE_PAM
  			pam_port_cludge = port;
  			status = CheckPAMAuth(port, port->user_name, "");
+ #else
+ 			Assert(false);
  			break;
  #endif   /* USE_PAM */
  
  		case uaLDAP:
+ #ifdef USE_LDAP
  			status = CheckLDAPAuth(port);
  			break;
+ #else
+ 			Assert(false);
  #endif
  
  		case uaTrust:
***************
*** 713,731 **** pg_krb5_recvauth(Port *port)
  		return STATUS_ERROR;
  	}
  
! 	if (pg_krb_caseins_users)
! 		ret = pg_strncasecmp(port->user_name, kusername, SM_DATABASE_USER);
! 	else
! 		ret = strncmp(port->user_name, kusername, SM_DATABASE_USER);
! 	if (ret)
! 	{
! 		ereport(LOG,
! 				(errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")",
! 						port->user_name, kusername)));
! 		ret = STATUS_ERROR;
! 	}
! 	else
! 		ret = STATUS_OK;
  
  	krb5_free_ticket(pg_krb5_context, ticket);
  	krb5_auth_con_free(pg_krb5_context, auth_context);
--- 723,730 ----
  		return STATUS_ERROR;
  	}
  
! 	ret = check_usermap(port->hba->usermap, port->user_name, kusername,
! 						pg_krb_caseins_users);
  
  	krb5_free_ticket(pg_krb5_context, ticket);
  	krb5_auth_con_free(pg_krb5_context, auth_context);
***************
*** 733,748 **** pg_krb5_recvauth(Port *port)
  
  	return ret;
  }
- #else
- 
- static int
- pg_krb5_recvauth(Port *port)
- {
- 	ereport(LOG,
- 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- 			 errmsg("Kerberos 5 not implemented on this server")));
- 	return STATUS_ERROR;
- }
  #endif   /* KRB5 */
  
  
--- 732,737 ----
***************
*** 1020,1057 **** pg_GSS_recvauth(Port *port)
  		return STATUS_ERROR;
  	}
  
! 	if (pg_krb_caseins_users)
! 		ret = pg_strcasecmp(port->user_name, gbuf.value);
! 	else
! 		ret = strcmp(port->user_name, gbuf.value);
! 
! 	if (ret)
! 	{
! 		/* GSS name and PGUSER are not equivalent */
! 		elog(DEBUG2,
! 			 "provided username (%s) and GSSAPI username (%s) don't match",
! 			 port->user_name, (char *) gbuf.value);
! 
! 		gss_release_buffer(&lmin_s, &gbuf);
! 		return STATUS_ERROR;
! 	}
  
  	gss_release_buffer(&lmin_s, &gbuf);
  
  	return STATUS_OK;
  }
- 
- #else							/* no ENABLE_GSS */
- 
- static int
- pg_GSS_recvauth(Port *port)
- {
- 	ereport(LOG,
- 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- 			 errmsg("GSSAPI not implemented on this server")));
- 	return STATUS_ERROR;
- }
- 
  #endif   /* ENABLE_GSS */
  
  
--- 1009,1021 ----
  		return STATUS_ERROR;
  	}
  
! 	ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
! 						pg_krb_caseins_users);
  
  	gss_release_buffer(&lmin_s, &gbuf);
  
  	return STATUS_OK;
  }
  #endif   /* ENABLE_GSS */
  
  
***************
*** 1328,1357 **** pg_SSPI_recvauth(Port *port)
  	 * We have the username (without domain/realm) in accountname, compare to
  	 * the supplied value. In SSPI, always compare case insensitive.
  	 */
! 	if (pg_strcasecmp(port->user_name, accountname))
! 	{
! 		/* GSS name and PGUSER are not equivalent */
! 		elog(DEBUG2,
! 			 "provided username (%s) and SSPI username (%s) don't match",
! 			 port->user_name, accountname);
! 
! 		return STATUS_ERROR;
! 	}
! 
! 	return STATUS_OK;
  }
- 
- #else							/* no ENABLE_SSPI */
- 
- static int
- pg_SSPI_recvauth(Port *port)
- {
- 	ereport(LOG,
- 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- 			 errmsg("SSPI not implemented on this server")));
- 	return STATUS_ERROR;
- }
- 
  #endif   /* ENABLE_SSPI */
  
  
--- 1292,1299 ----
  	 * We have the username (without domain/realm) in accountname, compare to
  	 * the supplied value. In SSPI, always compare case insensitive.
  	 */
! 	return check_usermap(port->hba->usermap, port->user_name, accountname, true);
  }
  #endif   /* ENABLE_SSPI */
  
  
***************
*** 1795,1808 **** authident(hbaPort *port)
  			return STATUS_ERROR;
  	}
  
! 	ereport(DEBUG2,
! 			(errmsg("Ident protocol identifies remote user as \"%s\"",
! 					ident_user)));
! 
! 	if (check_ident_usermap(port->hba->usermap, port->user_name, ident_user))
! 		return STATUS_OK;
! 	else
! 		return STATUS_ERROR;
  }
  
  
--- 1737,1743 ----
  			return STATUS_ERROR;
  	}
  
! 	return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
  }
  
  
***************
*** 1913,1920 **** CheckPAMAuth(Port *port, char *user, char *password)
  														 * not allocated */
  
  	/* Optionally, one can set the service name in pg_hba.conf */
! 	if (port->hba->auth_arg && port->hba->auth_arg[0] != '\0')
! 		retval = pam_start(port->hba->auth_arg, "pgsql@",
  						   &pam_passw_conv, &pamh);
  	else
  		retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
--- 1848,1855 ----
  														 * not allocated */
  
  	/* Optionally, one can set the service name in pg_hba.conf */
! 	if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
! 		retval = pam_start(port->hba->pamservice, "pgsql@",
  						   &pam_passw_conv, &pamh);
  	else
  		retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
***************
*** 2000,2075 **** static int
  CheckLDAPAuth(Port *port)
  {
  	char	   *passwd;
- 	char		server[128];
- 	char		basedn[128];
- 	char		prefix[128];
- 	char		suffix[128];
  	LDAP	   *ldap;
- 	bool		ssl = false;
  	int			r;
  	int			ldapversion = LDAP_VERSION3;
- 	int			ldapport = LDAP_PORT;
  	char		fulluser[NAMEDATALEN + 256 + 1];
  
! 	if (!port->hba->auth_arg || port->hba->auth_arg[0] == '\0')
  	{
  		ereport(LOG,
! 				(errmsg("LDAP configuration URL not specified")));
  		return STATUS_ERROR;
  	}
  
! 	/*
! 	 * Crack the LDAP url. We do a very trivial parse:
! 	 *
! 	 * ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
! 	 *
! 	 * This code originally used "%127s" for the suffix, but that doesn't
! 	 * work for embedded whitespace.  We know that tokens formed by
! 	 * hba.c won't include newlines, so we can use a "not newline" scanset
! 	 * instead.
! 	 */
! 
! 	server[0] = '\0';
! 	basedn[0] = '\0';
! 	prefix[0] = '\0';
! 	suffix[0] = '\0';
! 
! 	/* ldap, including port number */
! 	r = sscanf(port->hba->auth_arg,
! 			   "ldap://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
! 			   server, &ldapport, basedn, prefix, suffix);
! 	if (r < 3)
! 	{
! 		/* ldaps, including port number */
! 		r = sscanf(port->hba->auth_arg,
! 				   "ldaps://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
! 				   server, &ldapport, basedn, prefix, suffix);
! 		if (r >= 3)
! 			ssl = true;
! 	}
! 	if (r < 3)
! 	{
! 		/* ldap, no port number */
! 		r = sscanf(port->hba->auth_arg,
! 				   "ldap://%127[^/]/%127[^;];%127[^;];%127[^\n]",
! 				   server, basedn, prefix, suffix);
! 	}
! 	if (r < 2)
! 	{
! 		/* ldaps, no port number */
! 		r = sscanf(port->hba->auth_arg,
! 				   "ldaps://%127[^/]/%127[^;];%127[^;];%127[^\n]",
! 				   server, basedn, prefix, suffix);
! 		if (r >= 2)
! 			ssl = true;
! 	}
! 	if (r < 2)
! 	{
! 		ereport(LOG,
! 				(errmsg("invalid LDAP URL: \"%s\"",
! 						port->hba->auth_arg)));
! 		return STATUS_ERROR;
! 	}
  
  	sendAuthRequest(port, AUTH_REQ_PASSWORD);
  
--- 1935,1954 ----
  CheckLDAPAuth(Port *port)
  {
  	char	   *passwd;
  	LDAP	   *ldap;
  	int			r;
  	int			ldapversion = LDAP_VERSION3;
  	char		fulluser[NAMEDATALEN + 256 + 1];
  
! 	if (!port->hba->ldapserver|| port->hba->ldapserver[0] == '\0')
  	{
  		ereport(LOG,
! 				(errmsg("LDAP server not specified")));
  		return STATUS_ERROR;
  	}
  
! 	if (port->hba->ldapport == 0)
! 		port->hba->ldapport = LDAP_PORT;
  
  	sendAuthRequest(port, AUTH_REQ_PASSWORD);
  
***************
*** 2077,2083 **** CheckLDAPAuth(Port *port)
  	if (passwd == NULL)
  		return STATUS_EOF;		/* client wouldn't send password */
  
! 	ldap = ldap_init(server, ldapport);
  	if (!ldap)
  	{
  #ifndef WIN32
--- 1956,1962 ----
  	if (passwd == NULL)
  		return STATUS_EOF;		/* client wouldn't send password */
  
! 	ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
  	if (!ldap)
  	{
  #ifndef WIN32
***************
*** 2100,2106 **** CheckLDAPAuth(Port *port)
  		return STATUS_ERROR;
  	}
  
! 	if (ssl)
  	{
  #ifndef WIN32
  		if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
--- 1979,1985 ----
  		return STATUS_ERROR;
  	}
  
! 	if (port->hba->ldaptls)
  	{
  #ifndef WIN32
  		if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
***************
*** 2155,2161 **** CheckLDAPAuth(Port *port)
  	}
  
  	snprintf(fulluser, sizeof(fulluser), "%s%s%s",
! 			 prefix, port->user_name, suffix);
  	fulluser[sizeof(fulluser) - 1] = '\0';
  
  	r = ldap_simple_bind_s(ldap, fulluser, passwd);
--- 2034,2042 ----
  	}
  
  	snprintf(fulluser, sizeof(fulluser), "%s%s%s",
! 			 port->hba->ldapprefix?port->hba->ldapprefix:"",
! 			 port->user_name,
! 			 port->hba->ldapsuffix?port->hba->ldapsuffix:"");
  	fulluser[sizeof(fulluser) - 1] = '\0';
  
  	r = ldap_simple_bind_s(ldap, fulluser, passwd);
***************
*** 2165,2171 **** CheckLDAPAuth(Port *port)
  	{
  		ereport(LOG,
  				(errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
! 						fulluser, server, r)));
  		return STATUS_ERROR;
  	}
  
--- 2046,2052 ----
  	{
  		ereport(LOG,
  				(errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
! 						fulluser, port->hba->ldapserver, r)));
  		return STATUS_ERROR;
  	}
  
*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
***************
*** 565,570 **** check_db(const char *dbname, const char *role, char *param_str)
--- 565,606 ----
  
  
  /*
+  * Macros used to check and report on invalid configuration options.
+  * INVALID_AUTH_OPTION = reports when an option is specified for a method where it's
+  *                       not supported.
+  * REQUIRE_AUTH_OPTION = same as INVALID_AUTH_OPTION, except it also checks if the
+  *                       method is actually the one specified. Used as a shortcut when
+  *                       the option is only valid for one authentication method.
+  * MANDATORY_AUTH_ARG  = check if a required option is set for an authentication method,
+  *                       reporting error if it's not.
+  */
+ #define INVALID_AUTH_OPTION(optname, validmethods) do {\
+ 	ereport(LOG, \
+ 			(errcode(ERRCODE_CONFIG_FILE_ERROR), \
+ 			 errmsg("authentication option '%s' is only valid for authentication methods '%s'", \
+ 					optname, validmethods), \
+ 			 errcontext("line %d of configuration file \"%s\"", \
+ 					line_num, HbaFileName))); \
+ 	goto hba_other_error; \
+ } while (0)
+ 
+ #define REQUIRE_AUTH_OPTION(methodval, optname, validmethods) \
+ 	if (parsedline->auth_method != methodval) \
+ 		INVALID_AUTH_OPTION("ldaptls", "ldap")
+ 
+ #define MANDATORY_AUTH_ARG(argvar, argname, authname) \
+ if (argvar == NULL) {\
+ 	ereport(LOG, \
+ 			(errcode(ERRCODE_CONFIG_FILE_ERROR), \
+ 			 errmsg("authentication method '%s' requires argument '%s' to be set", \
+ 					authname, argname), \
+ 			 errcontext("line %d of configuration file \"%s\"", \
+ 					line_num, HbaFileName))); \
+ 	goto hba_other_error; \
+ } while (0);
+ 
+ 
+ /*
   * Parse one line in the hba config file and store the result in
   * a HbaLine structure.
   */
***************
*** 801,838 **** parse_hba_line(List *line, int line_num, HbaLine *parsedline)
  		goto hba_other_error;
  	}
  
! 	/* Get the authentication argument token, if any */
! 	line_item = lnext(line_item);
! 	if (line_item)
  	{
  		token = lfirst(line_item);
- 		parsedline->auth_arg= pstrdup(token);
- 	}
  
! 	/* 
! 	 * Backwards compatible format of ident authentication - support "naked" ident map
! 	 * name, as well as "sameuser"/"samerole"
! 	 */
! 	if (parsedline->auth_method == uaIdent)
! 	{
! 		if (parsedline->auth_arg && strlen(parsedline->auth_arg))
  		{
! 			if (strcmp(parsedline->auth_arg, "sameuser\n") == 0 ||
! 				strcmp(parsedline->auth_arg, "samerole\n") == 0)
  			{
! 				/* This is now the default */
! 				pfree(parsedline->auth_arg);
! 				parsedline->auth_arg = NULL;
! 				parsedline->usermap = NULL;
  			}
  			else
  			{
! 				/* Specific ident map specified */
! 				parsedline->usermap = parsedline->auth_arg;
! 				parsedline->auth_arg = NULL;
  			}
  		}
  	}
  	
  	return true;
  
--- 837,938 ----
  		goto hba_other_error;
  	}
  
! 	/* Parse remaining arguments */
! 	while ((line_item = lnext(line_item)) != NULL)
  	{
+ 		char *c;
+ 
  		token = lfirst(line_item);
  
! 		c = strchr(token, '=');
! 		if (c == NULL)
  		{
! 			/* 
! 			 * Got something that's not a name=value pair.
! 			 *
! 			 * XXX: attempt to do some backwards compatible parsing here?
! 			 */
! 			ereport(LOG,
! 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
! 					 errmsg("authentication option not in name=value format: %s", token),
! 					 errcontext("line %d of configuration file \"%s\"",
! 								line_num, HbaFileName)));
! 			goto hba_other_error;
! 		}
! 		else
! 		{
! 			*c++ = '\0'; /* token now holds "name", c holds "value" */
! 			if (strcmp(token, "map") == 0)
! 			{
! 				if (parsedline->auth_method != uaIdent &&
! 					parsedline->auth_method != uaKrb5 &&
! 					parsedline->auth_method != uaGSS &&
! 					parsedline->auth_method != uaSSPI)
! 					INVALID_AUTH_OPTION("map", "ident, krb5, gssapi and sspi");
! 				parsedline->usermap = pstrdup(c);
! 			}
! 			else if (strcmp(token, "pamservice") == 0)
! 			{
! 				REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
! 				parsedline->pamservice = pstrdup(c);
! 			}
! 			else if (strcmp(token, "ldaptls") == 0)
! 			{
! 				REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
! 				if (strcmp(c, "1") == 0)
! 					parsedline->ldaptls = true;
! 				else
! 					parsedline->ldaptls = false;
! 			}
! 			else if (strcmp(token, "ldapserver") == 0)
! 			{
! 				REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
! 				parsedline->ldapserver = pstrdup(c);
! 			}
! 			else if (strcmp(token, "ldapport") == 0)
! 			{
! 				REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
! 				parsedline->ldapport = atoi(c);
! 				if (parsedline->ldapport == 0)
! 				{
! 					ereport(LOG,
! 							(errcode(ERRCODE_CONFIG_FILE_ERROR),
! 							 errmsg("invalid ldap port '%s'", c),
! 							 errcontext("line %d of configuration file \"%s\"",
! 										line_num, HbaFileName)));
! 					goto hba_other_error;
! 				}
! 			}
! 			else if (strcmp(token, "ldapprefix") == 0)
  			{
! 				REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
! 				parsedline->ldapprefix = pstrdup(c);
! 			}
! 			else if (strcmp(token, "ldapsuffix") == 0)
! 			{
! 				REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
! 				parsedline->ldapsuffix = pstrdup(c);
  			}
  			else
  			{
! 				ereport(LOG,
! 						(errcode(ERRCODE_CONFIG_FILE_ERROR),
! 						 errmsg("unknown authentication option name '%s'", token),
! 						 errcontext("line %d of configuration file \"%s\"",
! 									line_num, HbaFileName)));
! 				goto hba_other_error;
  			}
  		}
  	}
+ 
+ 	/*
+ 	 * Check if the selected authentication method has any mandatory arguments that
+ 	 * are not set.
+ 	 */
+ 	if (parsedline->auth_method == uaLDAP)
+ 	{
+ 		MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
+ 	}
  	
  	return true;
  
***************
*** 1018,1025 **** free_hba_record(HbaLine *record)
  		pfree(record->database);
  	if (record->role)
  		pfree(record->role);
! 	if (record->auth_arg)
! 		pfree(record->auth_arg);
  }
  
  /*
--- 1118,1131 ----
  		pfree(record->database);
  	if (record->role)
  		pfree(record->role);
! 	if (record->pamservice)
! 		pfree(record->pamservice);
! 	if (record->ldapserver)
! 		pfree(record->ldapserver);
! 	if (record->ldapprefix)
! 		pfree(record->ldapprefix);
! 	if (record->ldapsuffix)
! 		pfree(record->ldapsuffix);
  }
  
  /*
***************
*** 1150,1156 **** read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
  static void
  parse_ident_usermap(List *line, int line_number, const char *usermap_name,
  					const char *pg_role, const char *ident_user,
! 					bool *found_p, bool *error_p)
  {
  	ListCell   *line_item;
  	char	   *token;
--- 1256,1262 ----
  static void
  parse_ident_usermap(List *line, int line_number, const char *usermap_name,
  					const char *pg_role, const char *ident_user,
! 					bool case_insensitive, bool *found_p, bool *error_p)
  {
  	ListCell   *line_item;
  	char	   *token;
***************
*** 1183,1192 **** parse_ident_usermap(List *line, int line_number, const char *usermap_name,
  	file_pgrole = token;
  
  	/* Match? */
! 	if (strcmp(file_map, usermap_name) == 0 &&
! 		strcmp(file_pgrole, pg_role) == 0 &&
! 		strcmp(file_ident_user, ident_user) == 0)
! 		*found_p = true;
  
  	return;
  
--- 1289,1308 ----
  	file_pgrole = token;
  
  	/* Match? */
! 	if (case_insensitive)
! 	{
! 		if (strcmp(file_map, usermap_name) == 0 &&
! 			pg_strcasecmp(file_pgrole, pg_role) == 0 &&
! 			pg_strcasecmp(file_ident_user, ident_user) == 0)
! 			*found_p = true;
! 	}
! 	else
! 	{
! 		if (strcmp(file_map, usermap_name) == 0 &&
! 			strcmp(file_pgrole, pg_role) == 0 &&
! 			strcmp(file_ident_user, ident_user) == 0)
! 			*found_p = true;
! 	}
  
  	return;
  
***************
*** 1210,1231 **** ident_syntax:
   *	file.  That's an implied map where "pgrole" must be identical to
   *	"ident_user" in order to be authorized.
   *
!  *	Iff authorized, return true.
   */
! bool
! check_ident_usermap(const char *usermap_name,
  					const char *pg_role,
! 					const char *ident_user)
  {
  	bool		found_entry = false,
  				error = false;
  
  	if (usermap_name == NULL || usermap_name[0] == '\0')
  	{
! 		if (strcmp(pg_role, ident_user) == 0)
! 			found_entry = true;
! 		else
! 			found_entry = false;
  	}
  	else
  	{
--- 1326,1357 ----
   *	file.  That's an implied map where "pgrole" must be identical to
   *	"ident_user" in order to be authorized.
   *
!  *	Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
   */
! int
! check_usermap(const char *usermap_name,
  					const char *pg_role,
! 					const char *auth_user,
! 					bool case_insensitive)
  {
  	bool		found_entry = false,
  				error = false;
  
  	if (usermap_name == NULL || usermap_name[0] == '\0')
  	{
! 		if (case_insensitive)
! 		{
! 			if (pg_strcasecmp(pg_role, auth_user) == 0)
! 				return STATUS_OK;
! 		}
! 		else {
! 			if (strcmp(pg_role, auth_user) == 0)
! 				return STATUS_OK;
! 		}
! 		ereport(LOG,
! 				(errmsg("provided username (%s) and authenticated username (%s) don't match",
! 						auth_user, pg_role)));
! 		return STATUS_ERROR;
  	}
  	else
  	{
***************
*** 1235,1247 **** check_ident_usermap(const char *usermap_name,
  		forboth(line_cell, ident_lines, num_cell, ident_line_nums)
  		{
  			parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
! 								usermap_name, pg_role, ident_user,
  								&found_entry, &error);
  			if (found_entry || error)
  				break;
  		}
  	}
! 	return found_entry;
  }
  
  
--- 1361,1380 ----
  		forboth(line_cell, ident_lines, num_cell, ident_line_nums)
  		{
  			parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
! 								usermap_name, pg_role, auth_user, case_insensitive,
  								&found_entry, &error);
  			if (found_entry || error)
  				break;
  		}
  	}
! 	if (!found_entry && !error)
! 	{
! 		ereport(LOG,
! 				(errmsg("no match in usermap for user '%s' authenticated as '%s'",
! 						pg_role, auth_user),
! 				 errcontext("usermap '%s'", usermap_name)));
! 	}
! 	return found_entry?STATUS_OK:STATUS_ERROR;
  }
  
  
*** a/src/backend/libpq/pg_hba.conf.sample
--- b/src/backend/libpq/pg_hba.conf.sample
***************
*** 9,18 ****
  # are authenticated, which PostgreSQL user names they can use, which
  # databases they can access.  Records take one of these forms:
  #
! # local      DATABASE  USER  METHOD  [OPTION]
! # host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
! # hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
! # hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
  #
  # (The uppercase items must be replaced by actual values.)
  #
--- 9,18 ----
  # are authenticated, which PostgreSQL user names they can use, which
  # databases they can access.  Records take one of these forms:
  #
! # local      DATABASE  USER  METHOD  [OPTIONS]
! # host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
! # hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
! # hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
  #
  # (The uppercase items must be replaced by actual values.)
  #
***************
*** 38,44 ****
  # "krb5", "ident", "pam" or "ldap".  Note that "password" sends passwords
  # in clear text; "md5" is preferred since it sends encrypted passwords.
  #
! # OPTION is the ident map or the name of the PAM service, depending on METHOD.
  #
  # Database and user names containing spaces, commas, quotes and other special
  # characters must be quoted. Quoting one of the keywords "all", "sameuser" or
--- 38,47 ----
  # "krb5", "ident", "pam" or "ldap".  Note that "password" sends passwords
  # in clear text; "md5" is preferred since it sends encrypted passwords.
  #
! # OPTIONS are a set of options for the authentication in the format
! # NAME=VALUE. The available options depend on the different authentication
! # methods - refer to the "Client Authentication" section in the documentation
! # for a list of which options are available for which authentication methods.
  #
  # Database and user names containing spaces, commas, quotes and other special
  # characters must be quoted. Quoting one of the keywords "all", "sameuser" or
*** a/src/backend/libpq/pg_ident.conf.sample
--- b/src/backend/libpq/pg_ident.conf.sample
***************
*** 5,22 ****
  # Authentication" for a complete description.  A short synopsis
  # follows.
  #
! # This file controls PostgreSQL ident-based authentication. It maps
! # ident user names (typically Unix user names) to their corresponding
  # PostgreSQL user names.  Records are of the form:
  #
! # MAPNAME  IDENT-USERNAME  PG-USERNAME
  #
  # (The uppercase quantities must be replaced by actual values.)
  #
  # MAPNAME is the (otherwise freely chosen) map name that was used in
! # pg_hba.conf.  IDENT-USERNAME is the detected user name of the
  # client.  PG-USERNAME is the requested PostgreSQL user name.  The
! # existence of a record specifies that IDENT-USERNAME may connect as
  # PG-USERNAME.  Multiple maps may be specified in this file and used
  # by pg_hba.conf.
  #
--- 5,22 ----
  # Authentication" for a complete description.  A short synopsis
  # follows.
  #
! # This file controls PostgreSQL username mapping. It maps
! # external user names to their corresponding
  # PostgreSQL user names.  Records are of the form:
  #
! # MAPNAME  SYSTEM-USERNAME  PG-USERNAME
  #
  # (The uppercase quantities must be replaced by actual values.)
  #
  # MAPNAME is the (otherwise freely chosen) map name that was used in
! # pg_hba.conf.  SYSTEM-USERNAME is the detected user name of the
  # client.  PG-USERNAME is the requested PostgreSQL user name.  The
! # existence of a record specifies that SYSTEM-USERNAME may connect as
  # PG-USERNAME.  Multiple maps may be specified in this file and used
  # by pg_hba.conf.
  #
***************
*** 28,35 ****
  # Put your actual configuration here
  # ----------------------------------
  #
! # No map names are defined in the default configuration.  If all ident
  # user names and PostgreSQL user names are the same, you don't need
  # this file.
  
! # MAPNAME     IDENT-USERNAME    PG-USERNAME
--- 28,35 ----
  # Put your actual configuration here
  # ----------------------------------
  #
! # No map names are defined in the default configuration.  If all system
  # user names and PostgreSQL user names are the same, you don't need
  # this file.
  
! # MAPNAME     SYSTEM-USERNAME    PG-USERNAME
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
***************
*** 25,37 **** typedef enum UserAuth
  	uaCrypt,
  	uaMD5,
  	uaGSS,
! 	uaSSPI
! #ifdef USE_PAM
! 	,uaPAM
! #endif   /* USE_PAM */
! #ifdef USE_LDAP
! 	,uaLDAP
! #endif
  } UserAuth;
  
  typedef enum ConnType
--- 25,33 ----
  	uaCrypt,
  	uaMD5,
  	uaGSS,
! 	uaSSPI,
! 	uaPAM,
! 	uaLDAP
  } UserAuth;
  
  typedef enum ConnType
***************
*** 51,58 **** typedef struct
  	struct sockaddr_storage addr;
  	struct sockaddr_storage mask;
  	UserAuth	auth_method;
  	char	   *usermap;
! 	char	   *auth_arg;
  } HbaLine;
  
  typedef struct Port hbaPort;
--- 47,60 ----
  	struct sockaddr_storage addr;
  	struct sockaddr_storage mask;
  	UserAuth	auth_method;
+ 
  	char	   *usermap;
! 	char	   *pamservice;
! 	bool		ldaptls;
! 	char	   *ldapserver;
! 	int			ldapport;
! 	char	   *ldapprefix;
! 	char	   *ldapsuffix;
  } HbaLine;
  
  typedef struct Port hbaPort;
***************
*** 64,71 **** extern void load_role(void);
  extern int	hba_getauthmethod(hbaPort *port);
  extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
  					  Oid *dbtablespace, TransactionId *dbfrozenxid);
! extern bool check_ident_usermap(const char *usermap_name,
! 					  const char *pg_role, const char *ident_user);
  extern bool pg_isblank(const char c);
  
  #endif   /* HBA_H */
--- 66,74 ----
  extern int	hba_getauthmethod(hbaPort *port);
  extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
  					  Oid *dbtablespace, TransactionId *dbfrozenxid);
! extern int  check_usermap(const char *usermap_name,
! 					  const char *pg_role, const char *auth_user,
! 					  bool case_sensitive);
  extern bool pg_isblank(const char c);
  
  #endif   /* HBA_H */
