diff -crN git/src/backend/catalog/system_views.sql Git_code/postgresql/src/backend/catalog/system_views.sql *** git/src/backend/catalog/system_views.sql Wed Mar 19 10:09:05 2014 --- Git_code/postgresql/src/backend/catalog/system_views.sql Fri Mar 14 12:11:26 2014 *************** *** 381,386 **** --- 381,391 ---- GRANT SELECT, UPDATE ON pg_settings TO PUBLIC; + CREATE VIEW pg_hba_settings AS + SELECT * FROM pg_show_all_hba_settings() AS A; + + REVOKE ALL on pg_hba_settings FROM public; + CREATE VIEW pg_timezone_abbrevs AS SELECT * FROM pg_timezone_abbrevs(); diff -crN git/src/backend/libpq/hba.c Git_code/postgresql/src/backend/libpq/hba.c *** git/src/backend/libpq/hba.c Wed Mar 19 10:09:06 2014 --- Git_code/postgresql/src/backend/libpq/hba.c Wed Mar 19 12:14:41 2014 *************** *** 2243,2245 **** --- 2243,2569 ---- { check_hba(port); } + int + GetNumHbaLines(void) + { + return (list_length(parsed_hba_lines)); + } + + /* + * Fetches the HbaLine corresponding to linenum variable. + * Fill the values required to build a tuple, of view pg_hba_settings, in values pointer. + */ + void + GetHbaLineByNum(int linenum, const char **values) + { + HbaLine *hba; + ListCell *dbcell; + char buffer[256]; + int len; + StringInfoData str; + HbaToken *tok; + + initStringInfo(&str); + hba = (HbaLine *) list_nth(parsed_hba_lines, linenum); + + /* Retrieving connection type */ + switch (hba->conntype) + { + case ctLocal: + values[0] = pstrdup("Local"); + break; + case ctHost: + values[0] = pstrdup("Host"); + break; + case ctHostSSL: + values[0] = pstrdup("HostSSL"); + break; + case ctHostNoSSL: + values[0] = pstrdup("HostNoSSL"); + break; + default: + values[0] = NULL; + break; + } + + appendStringInfoString(&str, "{"); + foreach(dbcell, hba->databases) + { + tok = lfirst(dbcell); + appendStringInfoString(&str, tok->string); + appendStringInfoString(&str, ","); + } + + /* + * For any number of values inserted, separator at the end needs to be + * replaced by string terminator + */ + if (str.len > 1) + { + str.data[str.len - 1] = '\0'; + str.len -= 1; + appendStringInfoString(&str, "}"); + values[1] = str.data; + } + else + values[1] = NULL; + + /* Retrieving user roles */ + initStringInfo(&str); + appendStringInfoString(&str, "{"); + foreach(dbcell, hba->roles) + { + tok = lfirst(dbcell); + appendStringInfoString(&str, tok->string); + appendStringInfoString(&str, ","); + } + /* Replace last separator by string terminator */ + if (str.len > 1) + { + str.data[str.len - 1] = '\0'; + str.len -= 1; + appendStringInfoString(&str, "}"); + values[2] = str.data; + } + else + values[2] = NULL; + + /* Retrieving Socket address */ + switch (hba->addr.ss_family) + { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + #ifdef HAVE_IPV6 + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + #endif + default: + len = sizeof(struct sockaddr_storage); + break; + } + if (getnameinfo((const struct sockaddr *) & hba->addr, len, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST) == 0) + values[3] = pstrdup(buffer); + else + values[3] = NULL; + + /* Retrieving socket mask */ + switch (hba->mask.ss_family) + { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + #ifdef HAVE_IPV6 + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + #endif + default: + len = sizeof(struct sockaddr_storage); + break; + } + if (getnameinfo((const struct sockaddr *) & hba->mask, len, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST) == 0) + values[4] = pstrdup(buffer); + else + values[4] = NULL; + + /* Retrieving compare method */ + switch (hba->ip_cmp_method) + { + case ipCmpMask: + values[5] = pstrdup("Mask"); + break; + case ipCmpSameHost: + values[5] = pstrdup("SameHost"); + break; + case ipCmpSameNet: + values[5] = pstrdup("SameNet"); + break; + case ipCmpAll: + values[5] = pstrdup("All"); + break; + default: + values[5] = NULL; + break; + } + + /* Retrieving hostname */ + values[6] = hba->hostname; + switch (hba->auth_method) + { + case uaReject: + values[7] = pstrdup("Reject"); + break; + case uaImplicitReject: + values[7] = pstrdup("ImplicitReject"); + break; + case uaTrust: + values[7] = pstrdup("Trust"); + break; + case uaIdent: + values[7] = pstrdup("Ident"); + break; + case uaPassword: + values[7] = pstrdup("Password"); + break; + case uaMD5: + values[7] = pstrdup("MD5"); + break; + case uaGSS: + values[7] = pstrdup("GSS"); + break; + case uaSSPI: + values[7] = pstrdup("SSPI"); + break; + case uaPAM: + values[7] = pstrdup("PAM"); + break; + case uaLDAP: + values[7] = pstrdup("LDAP"); + break; + case uaCert: + values[7] = pstrdup("Cert"); + break; + case uaRADIUS: + values[7] = pstrdup("RADIUS"); + break; + case uaPeer: + values[7] = pstrdup("Peer"); + break; + default: + values[7] = NULL; + break; + } + /* Retrieving configuration options set for authentication method */ + + initStringInfo(&str); + appendStringInfoString(&str, "{"); + + if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI) + { + if (hba->include_realm) + appendStringInfoString(&str, "include_realm=true,"); + if (hba->krb_realm) + { + appendStringInfoString(&str, "krb_realm="); + appendStringInfoString(&str, pstrdup(hba->krb_realm)); + appendStringInfoString(&str, ","); + } + + } + if ((hba->usermap) && (hba->auth_method == uaIdent || hba->auth_method == uaPeer || hba->auth_method == uaCert || hba->auth_method == uaGSS || hba->auth_method == uaSSPI)) + { + appendStringInfoString(&str, "map="); + appendStringInfoString(&str, pstrdup(hba->usermap)); + appendStringInfoString(&str, ","); + } + if (hba->auth_method == uaLDAP) + { + if (hba->ldapserver) + { + appendStringInfoString(&str, "ldapserver="); + appendStringInfoString(&str, pstrdup(hba->ldapserver)); + appendStringInfoString(&str, ","); + } + if (hba->ldapport) + { + snprintf(buffer, sizeof(buffer), "%d", hba->ldapport); + appendStringInfoString(&str, "ldapport="); + appendStringInfoString(&str, pstrdup(buffer)); + appendStringInfoString(&str, ","); + } + if (hba->ldaptls) + appendStringInfoString(&str, "ldaptls=true,"); + + if (hba->ldapprefix) + { + appendStringInfoString(&str, "ldapprefix="); + appendStringInfoString(&str, pstrdup(hba->ldapprefix)); + appendStringInfoString(&str, ","); + } + if (hba->ldapsuffix) + { + appendStringInfoString(&str, "ldapsuffix="); + appendStringInfoString(&str, pstrdup(hba->ldapsuffix)); + appendStringInfoString(&str, ","); + + } + if (hba->ldapbasedn) + { + appendStringInfoString(&str, "ldapbasedn="); + appendStringInfoString(&str, pstrdup(hba->ldapbasedn)); + appendStringInfoString(&str, ","); + + } + if (hba->ldapbinddn) + { + appendStringInfoString(&str, "ldapbinddn="); + appendStringInfoString(&str, pstrdup(hba->ldapbinddn)); + appendStringInfoString(&str, ","); + } + if (hba->ldapbindpasswd) + { + appendStringInfoString(&str, "ldapbindpasswd="); + appendStringInfoString(&str, pstrdup(hba->ldapbindpasswd)); + appendStringInfoString(&str, ","); + + } + if (hba->ldapsearchattribute) + { + appendStringInfoString(&str, "ldapsearchattribute="); + appendStringInfoString(&str, pstrdup(hba->ldapsearchattribute)); + appendStringInfoString(&str, ","); + } + if (hba->ldapscope) + { + snprintf(buffer, sizeof(buffer), "%d", hba->ldapscope); + appendStringInfoString(&str, "ldapscope="); + appendStringInfoString(&str, pstrdup(buffer)); + appendStringInfoString(&str, ","); + + } + + } + if (hba->auth_method == uaRADIUS) + { + if (hba->radiusserver) + { + appendStringInfoString(&str, "radiusserver="); + appendStringInfoString(&str, pstrdup(hba->radiusserver)); + appendStringInfoString(&str, ","); + } + if (hba->radiussecret) + { + appendStringInfoString(&str, "radiussecret="); + appendStringInfoString(&str, pstrdup(hba->radiussecret)); + appendStringInfoString(&str, ","); + } + if (hba->radiusidentifier) + { + appendStringInfoString(&str, "radiusidentifier="); + appendStringInfoString(&str, pstrdup(hba->radiusidentifier)); + appendStringInfoString(&str, ","); + } + if (hba->radiusport) + { + snprintf(buffer, sizeof(buffer), "%d", hba->radiusport); + appendStringInfoString(&str, "radiusport="); + appendStringInfoString(&str, pstrdup(buffer)); + appendStringInfoString(&str, ","); + } + } + if (str.len > 1) + { + str.data[str.len - 1] = '\0'; + str.len -= 1; + appendStringInfoString(&str, "}"); + values[8] = str.data; + } + else + values[8] = NULL; + + /* Retrieving linenumber */ + snprintf(buffer, sizeof(buffer), "%d", hba->linenumber); + values[9] = pstrdup(buffer); + } diff -crN git/src/backend/utils/misc/guc.c Git_code/postgresql/src/backend/utils/misc/guc.c *** git/src/backend/utils/misc/guc.c Wed Mar 19 10:09:18 2014 --- Git_code/postgresql/src/backend/utils/misc/guc.c Wed Mar 19 12:15:00 2014 *************** *** 129,134 **** --- 129,135 ---- extern char *SSLECDHCurve; extern bool SSLPreferServerCiphers; + extern List *parsed_hba_lines; #ifdef TRACE_SORT extern bool trace_sort; #endif *************** *** 7971,7976 **** --- 7973,8065 ---- SRF_RETURN_DONE(funcctx); } } + #define NUM_PG_HBA_SETTINGS_ATTS 10 + Datum + show_all_hba_settings(PG_FUNCTION_ARGS) + { + FuncCallContext *funcctx; + TupleDesc tupdesc; + int call_cntr; + int max_calls; + AttInMetadata *attinmeta; + MemoryContext oldcontext; + + /* stuff done only on the first call of the function */ + if (SRF_IS_FIRSTCALL()) + { + /* create a function context for cross-call persistence */ + funcctx = SRF_FIRSTCALL_INIT(); + + /* + * switch to memory context appropriate for multiple function calls + */ + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + /* + * need a tuple descriptor representing NUM_PG_HBA_SETTINGS_ATTS + * columns of the appropriate types + */ + tupdesc = CreateTemplateTupleDesc(NUM_PG_HBA_SETTINGS_ATTS, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "connection_type", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "databases", + TEXTARRAYOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "roles", + TEXTARRAYOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "socket_address", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "socket_mask", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "compare_method", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "hostname", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "authmethod", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "configuration_options", + TEXTARRAYOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "linenumber", + INT4OID, -1, 0); + + /* + * Generate attribute metadata needed later to produce tuples from raw + * C strings + */ + attinmeta = TupleDescGetAttInMetadata(tupdesc); + funcctx->attinmeta = attinmeta; + + /* total number of tuples to be returned */ + funcctx->max_calls = GetNumHbaLines(); + MemoryContextSwitchTo(oldcontext); + } + + /* stuff done on every call of the function */ + funcctx = SRF_PERCALL_SETUP(); + + call_cntr = funcctx->call_cntr; + max_calls = funcctx->max_calls; + attinmeta = funcctx->attinmeta; + + if (call_cntr < max_calls) + { + char *values[NUM_PG_HBA_SETTINGS_ATTS]; + HeapTuple tuple; + Datum result; + + /* Get the next parsed hba line values */ + GetHbaLineByNum(call_cntr, (const char **) values); + /* build a tuple */ + tuple = BuildTupleFromCStrings(attinmeta, values); + /* make the tuple into a datum */ + result = HeapTupleGetDatum(tuple); + SRF_RETURN_NEXT(funcctx, result); + } + else + { + /* do when there is no more left */ + SRF_RETURN_DONE(funcctx); + } + } static char * _ShowOption(struct config_generic * record, bool use_units) diff -crN git/src/include/catalog/pg_proc.h Git_code/postgresql/src/include/catalog/pg_proc.h *** git/src/include/catalog/pg_proc.h Wed Mar 19 10:09:09 2014 --- Git_code/postgresql/src/include/catalog/pg_proc.h Wed Mar 19 10:27:23 2014 *************** *** 2924,2929 **** --- 2924,2931 ---- DESCR("SET X as a function"); DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t s 0 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,1009,25,25,25,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline}" _null_ show_all_settings _null_ _null_ _null_ )); DESCR("SHOW ALL as a function"); + DATA(insert OID = 3206 ( pg_show_all_hba_settings PGNSP PGUID 12 1 1000 0 0 f f f f t t s 0 0 2249 "" "{25,1009,1009,25,25,25,25,25,1009,23}" "{o,o,o,o,o,o,o,o,o,o}" "{connection_type,databases,roles,socket_address,socket_mask,compare_method,hostname,authmethod,configuration_options,linenumber}" _null_ show_all_hba_settings _null_ _null_ _null_ )); + DESCR("SHOW ALL HBA settings as a function"); DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ pg_lock_status _null_ _null_ _null_ )); DESCR("view system lock information"); DATA(insert OID = 1065 ( pg_prepared_xact PGNSP PGUID 12 1 1000 0 0 f f f f t t v 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ pg_prepared_xact _null_ _null_ _null_ )); diff -crN git/src/include/libpq/hba.h Git_code/postgresql/src/include/libpq/hba.h *** git/src/include/libpq/hba.h Wed Mar 19 10:09:10 2014 --- Git_code/postgresql/src/include/libpq/hba.h Wed Mar 19 12:15:33 2014 *************** *** 103,107 **** const char *pg_role, const char *auth_user, bool case_sensitive); extern bool pg_isblank(const char c); ! #endif /* HBA_H */ --- 103,108 ---- const char *pg_role, const char *auth_user, bool case_sensitive); extern bool pg_isblank(const char c); ! extern void GetHbaLineByNum(int linenum, const char **values); ! extern int GetNumHbaLines(void); #endif /* HBA_H */ diff -crN git/src/include/utils/builtins.h Git_code/postgresql/src/include/utils/builtins.h *** git/src/include/utils/builtins.h Wed Mar 19 10:09:12 2014 --- Git_code/postgresql/src/include/utils/builtins.h Mon Mar 17 12:10:55 2014 *************** *** 1068,1073 **** --- 1068,1074 ---- extern Datum show_config_by_name(PG_FUNCTION_ARGS); extern Datum set_config_by_name(PG_FUNCTION_ARGS); extern Datum show_all_settings(PG_FUNCTION_ARGS); + extern Datum show_all_hba_settings(PG_FUNCTION_ARGS); /* lockfuncs.c */ extern Datum pg_lock_status(PG_FUNCTION_ARGS); diff -crN git/doc/src/sgml/catalogs.sgml Git_code/postgresql/doc/src/sgml/catalogs.sgml *** git/doc/src/sgml/catalogs.sgml Wed Mar 19 10:09:53 2014 --- Git_code/postgresql/doc/src/sgml/catalogs.sgml Wed Mar 19 10:26:47 2014 *************** *** 7227,7232 **** --- 7227,7237 ---- views + + pg_hba_settings + client authentication settings + + *************** *** 9419,9422 **** --- 9424,9509 ---- + + <structname>pg_hba_settings</structname> + + + pg_hba_settings + + + + The view pg_hba_settings provides access to + useful information about authentication details of Postgresql cluster. + For security reasons, access to this view is limited only to superusers. No update, insert or delete operations are allowed in this view. + + + + <structname>pg_hba_settings</> Columns + + + + + Name + Type + Description + + + + + connection_type + text + Type of connection + + + databases + text[] + List of database names + + + roles + text[] + List of user names + + + socket_address + text + Client machine address + + + socket_mask + text + IP Mask + + + compare_method + text + IP address comparision method + + + hostname + text + Client host name + + + authmethod + text + Authentication method + + + configuration_options + text[] + Configuration options set for authentication method + + + linenumber + integer + + Line number within client authentication configuration file + the current value was set at + + + + +
+
diff -crN git/doc/src/sgml/client-auth.sgml Git_code/postgresql/doc/src/sgml/client-auth.sgml *** git/doc/src/sgml/client-auth.sgml Wed Mar 19 10:09:53 2014 --- Git_code/postgresql/doc/src/sgml/client-auth.sgml Tue Mar 18 14:41:58 2014 *************** *** 675,680 **** --- 675,685 ---- local db1,db2,@demodbs all md5 + + + Details of this file can be accessed from pg_hba_settings view. + See for details. +