1 /*-------------------------------------------------------------------------
4 * Routines to handle host based authentication (that's the scheme
5 * wherein you authenticate a user by seeing what IP address the system
6 * says he comes from and choosing authentication method based on it).
8 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * src/backend/libpq/hba.c
15 *-------------------------------------------------------------------------
22 #include <sys/param.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
28 #include "catalog/pg_collation.h"
30 #include "libpq/libpq.h"
31 #include "postmaster/postmaster.h"
32 #include "regex/regex.h"
33 #include "replication/walsender.h"
34 #include "storage/fd.h"
35 #include "utils/acl.h"
36 #include "utils/guc.h"
37 #include "utils/lsyscache.h"
38 #include "utils/memutils.h"
41 #define atooid(x) ((Oid) strtoul((x), NULL, 10))
42 #define atoxid(x) ((TransactionId) strtoul((x), NULL, 10))
46 /* callback data for check_network_callback */
47 typedef struct check_network_data
49 IPCompareMethod method; /* test method */
50 SockAddr *raddr; /* client's actual address */
51 bool result; /* set to true if match */
55 #define token_is_keyword(t, k) (!t->quoted && strcmp(t->string, k) == 0)
56 #define token_matches(t, k) (strcmp(t->string, k) == 0)
59 * A single string token lexed from the HBA config file, together with whether
60 * the token had been quoted.
62 typedef struct HbaToken
69 * pre-parsed content of HBA config file: list of HbaLine structs.
70 * parsed_hba_context is the memory context where it lives.
72 static List *parsed_hba_lines = NIL;
73 static MemoryContext parsed_hba_context = NULL;
76 * These variables hold the pre-parsed contents of the ident usermap
77 * configuration file. ident_lines is a triple-nested list of lines, fields
78 * and tokens, as returned by tokenize_file. There will be one line in
79 * ident_lines for each (non-empty, non-comment) line of the file. Note there
80 * will always be at least one field, since blank lines are not entered in the
81 * data structure. ident_line_nums is an integer list containing the actual
82 * line number for each line represented in ident_lines. ident_context is
83 * the memory context holding all this.
85 static List *ident_lines = NIL;
86 static List *ident_line_nums = NIL;
87 static MemoryContext ident_context = NULL;
90 static MemoryContext tokenize_file(const char *filename, FILE *file,
91 List **lines, List **line_nums);
92 static List *tokenize_inc_file(List *tokens, const char *outer_filename,
93 const char *inc_filename);
94 static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
98 * isblank() exists in the ISO C99 spec, but it's not very portable yet,
99 * so provide our own version.
102 pg_isblank(const char c)
104 return c == ' ' || c == '\t' || c == '\r';
109 * Grab one token out of fp. Tokens are strings of non-blank
110 * characters bounded by blank characters, commas, beginning of line, and
111 * end of line. Blank means space or tab. Tokens can be delimited by
112 * double quotes (this allows the inclusion of blanks, but not newlines).
114 * The token, if any, is returned at *buf (a buffer of size bufsz).
115 * Also, we set *initial_quote to indicate whether there was quoting before
116 * the first character. (We use that to prevent "@x" from being treated
117 * as a file inclusion request. Note that @"x" should be so treated;
118 * we want to allow that to support embedded spaces in file paths.)
119 * We set *terminating_comma to indicate whether the token is terminated by a
120 * comma (which is not returned.)
122 * If successful: store null-terminated token at *buf and return TRUE.
123 * If no more tokens on line: set *buf = '\0' and return FALSE.
125 * Leave file positioned at the character immediately after the token or EOF,
126 * whichever comes first. If no more tokens on line, position the file to the
127 * beginning of the next line or EOF, whichever comes first.
132 next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
133 bool *terminating_comma)
136 char *start_buf = buf;
137 char *end_buf = buf + (bufsz - 2);
138 bool in_quote = false;
139 bool was_quote = false;
140 bool saw_quote = false;
142 /* end_buf reserves two bytes to ensure we can append \n and \0 */
143 Assert(end_buf > start_buf);
145 *initial_quote = false;
146 *terminating_comma = false;
148 /* Move over initial whitespace and commas */
149 while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
152 if (c == EOF || c == '\n')
159 * Build a token in buf of next characters up to EOF, EOL, unquoted comma,
160 * or unquoted whitespace.
162 while (c != EOF && c != '\n' &&
163 (!pg_isblank(c) || in_quote))
165 /* skip comments to EOL */
166 if (c == '#' && !in_quote)
168 while ((c = getc(fp)) != EOF && c != '\n')
170 /* If only comment, consume EOL too; return EOL */
171 if (c != EOF && buf == start_buf)
180 (errcode(ERRCODE_CONFIG_FILE_ERROR),
181 errmsg("authentication file token too long, skipping: \"%s\"",
183 /* Discard remainder of line */
184 while ((c = getc(fp)) != EOF && c != '\n')
189 /* we do not pass back the comma in the token */
190 if (c == ',' && !in_quote)
192 *terminating_comma = true;
196 if (c != '"' || was_quote)
199 /* Literal double-quote is two double-quotes */
200 if (in_quote && c == '"')
201 was_quote = !was_quote;
207 in_quote = !in_quote;
209 if (buf == start_buf)
210 *initial_quote = true;
217 * Put back the char right after the token (critical in case it is EOL,
218 * since we need to detect end-of-line at next call).
225 return (saw_quote || buf > start_buf);
229 make_hba_token(char *token, bool quoted)
234 toklen = strlen(token);
235 hbatoken = (HbaToken *) palloc(sizeof(HbaToken) + toklen + 1);
236 hbatoken->string = (char *) hbatoken + sizeof(HbaToken);
237 hbatoken->quoted = quoted;
238 memcpy(hbatoken->string, token, toklen + 1);
244 * Copy a HbaToken struct into freshly palloc'd memory.
247 copy_hba_token(HbaToken *in)
249 HbaToken *out = make_hba_token(in->string, in->quoted);
256 * Tokenize one HBA field from a file, handling file inclusion and comma lists.
258 * The result is a List of HbaToken structs for each individual token,
259 * or NIL if we reached EOL.
262 next_field_expand(const char *filename, FILE *file)
271 if (!next_token(file, buf, sizeof(buf), &initial_quote, &trailing_comma))
274 /* Is this referencing a file? */
275 if (!initial_quote && buf[0] == '@' && buf[1] != '\0')
276 tokens = tokenize_inc_file(tokens, filename, buf + 1);
278 tokens = lappend(tokens, make_hba_token(buf, initial_quote));
279 } while (trailing_comma);
286 * Expand a file included from another file into an hba "field"
288 * Opens and tokenises a file included from another HBA config file with @,
289 * and returns all values found therein as a flat list of HbaTokens. If a
290 * @-token is found, recursively expand it. The given token list is used as
291 * initial contents of list (so foo,bar,@baz does what you expect).
294 tokenize_inc_file(List *tokens,
295 const char *outer_filename,
296 const char *inc_filename)
303 MemoryContext linecxt;
305 if (is_absolute_path(inc_filename))
307 /* absolute path is taken as-is */
308 inc_fullname = pstrdup(inc_filename);
312 /* relative path is relative to dir of calling file */
313 inc_fullname = (char *) palloc(strlen(outer_filename) + 1 +
314 strlen(inc_filename) + 1);
315 strcpy(inc_fullname, outer_filename);
316 get_parent_directory(inc_fullname);
317 join_path_components(inc_fullname, inc_fullname, inc_filename);
318 canonicalize_path(inc_fullname);
321 inc_file = AllocateFile(inc_fullname, "r");
322 if (inc_file == NULL)
325 (errcode_for_file_access(),
326 errmsg("could not open secondary authentication file \"@%s\" as \"%s\": %m",
327 inc_filename, inc_fullname)));
332 /* There is possible recursion here if the file contains @ */
333 linecxt = tokenize_file(inc_fullname, inc_file, &inc_lines, &inc_line_nums);
338 foreach(inc_line, inc_lines)
340 List *inc_fields = lfirst(inc_line);
343 foreach(inc_field, inc_fields)
345 List *inc_tokens = lfirst(inc_field);
348 foreach(inc_token, inc_tokens)
350 HbaToken *token = lfirst(inc_token);
352 tokens = lappend(tokens, copy_hba_token(token));
357 MemoryContextDelete(linecxt);
362 * Tokenize the given file, storing the resulting data into two Lists: a
363 * List of lines, and a List of line numbers.
365 * The list of lines is a triple-nested List structure. Each line is a List of
366 * fields, and each field is a List of HbaTokens.
368 * filename must be the absolute path to the target file.
370 * Return value is a memory context which contains all memory allocated by
374 tokenize_file(const char *filename, FILE *file,
375 List **lines, List **line_nums)
377 List *current_line = NIL;
378 List *current_field = NIL;
380 MemoryContext linecxt;
381 MemoryContext oldcxt;
383 linecxt = AllocSetContextCreate(TopMemoryContext,
385 ALLOCSET_DEFAULT_MINSIZE,
386 ALLOCSET_DEFAULT_INITSIZE,
387 ALLOCSET_DEFAULT_MAXSIZE);
388 oldcxt = MemoryContextSwitchTo(linecxt);
390 *lines = *line_nums = NIL;
392 while (!feof(file) && !ferror(file))
394 current_field = next_field_expand(filename, file);
396 /* add tokens to list, unless we are at EOL or comment start */
397 if (list_length(current_field) > 0)
399 if (current_line == NIL)
401 /* make a new line List, record its line number */
402 current_line = lappend(current_line, current_field);
403 *lines = lappend(*lines, current_line);
404 *line_nums = lappend_int(*line_nums, line_number);
408 /* append tokens to current line's list */
409 current_line = lappend(current_line, current_field);
414 /* we are at real or logical EOL, so force a new line List */
420 MemoryContextSwitchTo(oldcxt);
427 * Does user belong to role?
429 * userid is the OID of the role given as the attempted login identifier.
430 * We check to see if it is a member of the specified role name.
433 is_member(Oid userid, const char *role)
437 if (!OidIsValid(userid))
438 return false; /* if user not exist, say "no" */
440 roleid = get_role_oid(role, true);
442 if (!OidIsValid(roleid))
443 return false; /* if target role not exist, say "no" */
446 * See if user is directly or indirectly a member of role. For this
447 * purpose, a superuser is not considered to be automatically a member of
448 * the role, so group auth only applies to explicit membership.
450 return is_member_of_role_nosuper(userid, roleid);
454 * Check HbaToken list for a match to role, allowing group names.
457 check_role(const char *role, Oid roleid, List *tokens)
462 foreach(cell, tokens)
465 if (!tok->quoted && tok->string[0] == '+')
467 if (is_member(roleid, tok->string + 1))
470 else if (token_matches(tok, role) ||
471 token_is_keyword(tok, "all"))
478 * Check to see if db/role combination matches HbaToken list.
481 check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
486 foreach(cell, tokens)
491 /* walsender connections can only match replication keyword */
492 if (token_is_keyword(tok, "replication"))
495 else if (token_is_keyword(tok, "all"))
497 else if (token_is_keyword(tok, "sameuser"))
499 if (strcmp(dbname, role) == 0)
502 else if (token_is_keyword(tok, "samegroup") ||
503 token_is_keyword(tok, "samerole"))
505 if (is_member(roleid, dbname))
508 else if (token_is_keyword(tok, "replication"))
509 continue; /* never match this if not walsender */
510 else if (token_matches(tok, dbname))
517 ipv4eq(struct sockaddr_in * a, struct sockaddr_in * b)
519 return (a->sin_addr.s_addr == b->sin_addr.s_addr);
525 ipv6eq(struct sockaddr_in6 * a, struct sockaddr_in6 * b)
529 for (i = 0; i < 16; i++)
530 if (a->sin6_addr.s6_addr[i] != b->sin6_addr.s6_addr[i])
535 #endif /* HAVE_IPV6 */
538 * Check whether host name matches pattern.
541 hostname_match(const char *pattern, const char *actual_hostname)
543 if (pattern[0] == '.') /* suffix match */
545 size_t plen = strlen(pattern);
546 size_t hlen = strlen(actual_hostname);
551 return (pg_strcasecmp(pattern, actual_hostname + (hlen - plen)) == 0);
554 return (pg_strcasecmp(pattern, actual_hostname) == 0);
558 * Check to see if a connecting IP matches a given host name.
561 check_hostname(hbaPort *port, const char *hostname)
563 struct addrinfo *gai_result,
568 /* Lookup remote host name if not already done */
569 if (!port->remote_hostname)
571 char remote_hostname[NI_MAXHOST];
573 if (pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
574 remote_hostname, sizeof(remote_hostname),
579 port->remote_hostname = pstrdup(remote_hostname);
582 if (!hostname_match(hostname, port->remote_hostname))
585 /* Lookup IP from host name and check against original IP */
587 if (port->remote_hostname_resolv == +1)
589 if (port->remote_hostname_resolv == -1)
592 ret = getaddrinfo(port->remote_hostname, NULL, NULL, &gai_result);
595 (errmsg("could not translate host name \"%s\" to address: %s",
596 port->remote_hostname, gai_strerror(ret))));
599 for (gai = gai_result; gai; gai = gai->ai_next)
601 if (gai->ai_addr->sa_family == port->raddr.addr.ss_family)
603 if (gai->ai_addr->sa_family == AF_INET)
605 if (ipv4eq((struct sockaddr_in *) gai->ai_addr,
606 (struct sockaddr_in *) & port->raddr.addr))
613 else if (gai->ai_addr->sa_family == AF_INET6)
615 if (ipv6eq((struct sockaddr_in6 *) gai->ai_addr,
616 (struct sockaddr_in6 *) & port->raddr.addr))
627 freeaddrinfo(gai_result);
630 elog(DEBUG2, "pg_hba.conf host name \"%s\" rejected because address resolution did not return a match with IP address of client",
633 port->remote_hostname_resolv = found ? +1 : -1;
639 * Check to see if a connecting IP matches the given address and netmask.
642 check_ip(SockAddr *raddr, struct sockaddr * addr, struct sockaddr * mask)
644 if (raddr->addr.ss_family == addr->sa_family)
646 /* Same address family */
647 if (!pg_range_sockaddr(&raddr->addr,
648 (struct sockaddr_storage *) addr,
649 (struct sockaddr_storage *) mask))
653 else if (addr->sa_family == AF_INET &&
654 raddr->addr.ss_family == AF_INET6)
657 * If we're connected on IPv6 but the file specifies an IPv4 address
658 * to match against, promote the latter to an IPv6 address before
659 * trying to match the client's address.
661 struct sockaddr_storage addrcopy,
664 memcpy(&addrcopy, &addr, sizeof(addrcopy));
665 memcpy(&maskcopy, &mask, sizeof(maskcopy));
666 pg_promote_v4_to_v6_addr(&addrcopy);
667 pg_promote_v4_to_v6_mask(&maskcopy);
669 if (!pg_range_sockaddr(&raddr->addr, &addrcopy, &maskcopy))
672 #endif /* HAVE_IPV6 */
675 /* Wrong address family, no IPV6 */
683 * pg_foreach_ifaddr callback: does client addr match this machine interface?
686 check_network_callback(struct sockaddr * addr, struct sockaddr * netmask,
689 check_network_data *cn = (check_network_data *) cb_data;
690 struct sockaddr_storage mask;
692 /* Already found a match? */
696 if (cn->method == ipCmpSameHost)
698 /* Make an all-ones netmask of appropriate length for family */
699 pg_sockaddr_cidr_mask(&mask, NULL, addr->sa_family);
700 cn->result = check_ip(cn->raddr, addr, (struct sockaddr *) & mask);
704 /* Use the netmask of the interface itself */
705 cn->result = check_ip(cn->raddr, addr, netmask);
710 * Use pg_foreach_ifaddr to check a samehost or samenet match
713 check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
715 check_network_data cn;
722 if (pg_foreach_ifaddr(check_network_callback, &cn) < 0)
724 elog(LOG, "error enumerating network interfaces: %m");
733 * Macros used to check and report on invalid configuration options.
734 * INVALID_AUTH_OPTION = reports when an option is specified for a method where it's
736 * REQUIRE_AUTH_OPTION = same as INVALID_AUTH_OPTION, except it also checks if the
737 * method is actually the one specified. Used as a shortcut when
738 * the option is only valid for one authentication method.
739 * MANDATORY_AUTH_ARG = check if a required option is set for an authentication method,
740 * reporting error if it's not.
742 #define INVALID_AUTH_OPTION(optname, validmethods) do {\
744 (errcode(ERRCODE_CONFIG_FILE_ERROR), \
745 /* translator: the second %s is a list of auth methods */ \
746 errmsg("authentication option \"%s\" is only valid for authentication methods %s", \
747 optname, _(validmethods)), \
748 errcontext("line %d of configuration file \"%s\"", \
749 line_num, HbaFileName))); \
753 #define REQUIRE_AUTH_OPTION(methodval, optname, validmethods) do {\
754 if (hbaline->auth_method != methodval) \
755 INVALID_AUTH_OPTION(optname, validmethods); \
758 #define MANDATORY_AUTH_ARG(argvar, argname, authname) do {\
759 if (argvar == NULL) {\
761 (errcode(ERRCODE_CONFIG_FILE_ERROR), \
762 errmsg("authentication method \"%s\" requires argument \"%s\" to be set", \
763 authname, argname), \
764 errcontext("line %d of configuration file \"%s\"", \
765 line_num, HbaFileName))); \
771 * IDENT_FIELD_ABSENT:
772 * Throw an error and exit the function if the given ident field ListCell is
776 * Throw an error and exit the function if the given ident token List has more
779 #define IDENT_FIELD_ABSENT(field) do {\
782 (errcode(ERRCODE_CONFIG_FILE_ERROR), \
783 errmsg("missing entry in file \"%s\" at end of line %d", \
784 IdentFileName, line_number))); \
790 #define IDENT_MULTI_VALUE(tokens) do {\
791 if (tokens->length > 1) { \
793 (errcode(ERRCODE_CONFIG_FILE_ERROR), \
794 errmsg("multiple values in ident field"), \
795 errcontext("line %d of configuration file \"%s\"", \
796 line_number, IdentFileName))); \
804 * Parse one tokenised line from the hba config file and store the result in a
805 * HbaLine structure, or NULL if parsing fails.
807 * The tokenised line is a List of fields, each field being a List of
810 * Note: this function leaks memory when an error occurs. Caller is expected
811 * to have set a memory context that will be reset if this function returns
815 parse_hba_line(List *line, int line_num)
818 struct addrinfo *gai_result;
819 struct addrinfo hints;
829 parsedline = palloc0(sizeof(HbaLine));
830 parsedline->linenumber = line_num;
832 /* Check the record type. */
833 field = list_head(line);
834 tokens = lfirst(field);
835 if (tokens->length > 1)
838 (errcode(ERRCODE_CONFIG_FILE_ERROR),
839 errmsg("multiple values specified for connection type"),
840 errhint("Specify exactly one connection type per line."),
841 errcontext("line %d of configuration file \"%s\"",
842 line_num, HbaFileName)));
845 token = linitial(tokens);
846 if (strcmp(token->string, "local") == 0)
848 #ifdef HAVE_UNIX_SOCKETS
849 parsedline->conntype = ctLocal;
852 (errcode(ERRCODE_CONFIG_FILE_ERROR),
853 errmsg("local connections are not supported by this build"),
854 errcontext("line %d of configuration file \"%s\"",
855 line_num, HbaFileName)));
859 else if (strcmp(token->string, "host") == 0 ||
860 strcmp(token->string, "hostssl") == 0 ||
861 strcmp(token->string, "hostnossl") == 0)
864 if (token->string[4] == 's') /* "hostssl" */
866 /* SSL support must be actually active, else complain */
869 parsedline->conntype = ctHostSSL;
873 (errcode(ERRCODE_CONFIG_FILE_ERROR),
874 errmsg("hostssl requires SSL to be turned on"),
875 errhint("Set ssl = on in postgresql.conf."),
876 errcontext("line %d of configuration file \"%s\"",
877 line_num, HbaFileName)));
882 (errcode(ERRCODE_CONFIG_FILE_ERROR),
883 errmsg("hostssl is not supported by this build"),
884 errhint("Compile with --with-openssl to use SSL connections."),
885 errcontext("line %d of configuration file \"%s\"",
886 line_num, HbaFileName)));
891 else if (token->string[4] == 'n') /* "hostnossl" */
893 parsedline->conntype = ctHostNoSSL;
898 /* "host", or "hostnossl" and SSL support not built in */
899 parsedline->conntype = ctHost;
905 (errcode(ERRCODE_CONFIG_FILE_ERROR),
906 errmsg("invalid connection type \"%s\"",
908 errcontext("line %d of configuration file \"%s\"",
909 line_num, HbaFileName)));
913 /* Get the databases. */
914 field = lnext(field);
918 (errcode(ERRCODE_CONFIG_FILE_ERROR),
919 errmsg("end-of-line before database specification"),
920 errcontext("line %d of configuration file \"%s\"",
921 line_num, HbaFileName)));
924 parsedline->databases = NIL;
925 tokens = lfirst(field);
926 foreach(tokencell, tokens)
928 parsedline->databases = lappend(parsedline->databases,
929 copy_hba_token(lfirst(tokencell)));
933 field = lnext(field);
937 (errcode(ERRCODE_CONFIG_FILE_ERROR),
938 errmsg("end-of-line before role specification"),
939 errcontext("line %d of configuration file \"%s\"",
940 line_num, HbaFileName)));
943 parsedline->roles = NIL;
944 tokens = lfirst(field);
945 foreach(tokencell, tokens)
947 parsedline->roles = lappend(parsedline->roles,
948 copy_hba_token(lfirst(tokencell)));
951 if (parsedline->conntype != ctLocal)
953 /* Read the IP address field. (with or without CIDR netmask) */
954 field = lnext(field);
958 (errcode(ERRCODE_CONFIG_FILE_ERROR),
959 errmsg("end-of-line before IP address specification"),
960 errcontext("line %d of configuration file \"%s\"",
961 line_num, HbaFileName)));
964 tokens = lfirst(field);
965 if (tokens->length > 1)
968 (errcode(ERRCODE_CONFIG_FILE_ERROR),
969 errmsg("multiple values specified for host address"),
970 errhint("Specify one address range per line."),
971 errcontext("line %d of configuration file \"%s\"",
972 line_num, HbaFileName)));
975 token = linitial(tokens);
977 if (token_is_keyword(token, "all"))
979 parsedline->ip_cmp_method = ipCmpAll;
981 else if (token_is_keyword(token, "samehost"))
983 /* Any IP on this host is allowed to connect */
984 parsedline->ip_cmp_method = ipCmpSameHost;
986 else if (token_is_keyword(token, "samenet"))
988 /* Any IP on the host's subnets is allowed to connect */
989 parsedline->ip_cmp_method = ipCmpSameNet;
993 /* IP and netmask are specified */
994 parsedline->ip_cmp_method = ipCmpMask;
996 /* need a modifiable copy of token */
997 str = pstrdup(token->string);
999 /* Check if it has a CIDR suffix and if so isolate it */
1000 cidr_slash = strchr(str, '/');
1004 /* Get the IP address either way */
1005 hints.ai_flags = AI_NUMERICHOST;
1006 hints.ai_family = PF_UNSPEC;
1007 hints.ai_socktype = 0;
1008 hints.ai_protocol = 0;
1009 hints.ai_addrlen = 0;
1010 hints.ai_canonname = NULL;
1011 hints.ai_addr = NULL;
1012 hints.ai_next = NULL;
1014 ret = pg_getaddrinfo_all(str, NULL, &hints, &gai_result);
1015 if (ret == 0 && gai_result)
1016 memcpy(&parsedline->addr, gai_result->ai_addr,
1017 gai_result->ai_addrlen);
1018 else if (ret == EAI_NONAME)
1019 parsedline->hostname = str;
1023 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1024 errmsg("invalid IP address \"%s\": %s",
1025 str, gai_strerror(ret)),
1026 errcontext("line %d of configuration file \"%s\"",
1027 line_num, HbaFileName)));
1029 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1033 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1035 /* Get the netmask */
1038 if (parsedline->hostname)
1041 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1042 errmsg("specifying both host name and CIDR mask is invalid: \"%s\"",
1044 errcontext("line %d of configuration file \"%s\"",
1045 line_num, HbaFileName)));
1049 if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
1050 parsedline->addr.ss_family) < 0)
1053 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1054 errmsg("invalid CIDR mask in address \"%s\"",
1056 errcontext("line %d of configuration file \"%s\"",
1057 line_num, HbaFileName)));
1062 else if (!parsedline->hostname)
1064 /* Read the mask field. */
1066 field = lnext(field);
1070 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1071 errmsg("end-of-line before netmask specification"),
1072 errhint("Specify an address range in CIDR notation, or provide a separate netmask."),
1073 errcontext("line %d of configuration file \"%s\"",
1074 line_num, HbaFileName)));
1077 tokens = lfirst(field);
1078 if (tokens->length > 1)
1081 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1082 errmsg("multiple values specified for netmask"),
1083 errcontext("line %d of configuration file \"%s\"",
1084 line_num, HbaFileName)));
1087 token = linitial(tokens);
1089 ret = pg_getaddrinfo_all(token->string, NULL,
1090 &hints, &gai_result);
1091 if (ret || !gai_result)
1094 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1095 errmsg("invalid IP mask \"%s\": %s",
1096 token->string, gai_strerror(ret)),
1097 errcontext("line %d of configuration file \"%s\"",
1098 line_num, HbaFileName)));
1100 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1104 memcpy(&parsedline->mask, gai_result->ai_addr,
1105 gai_result->ai_addrlen);
1106 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1108 if (parsedline->addr.ss_family != parsedline->mask.ss_family)
1111 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1112 errmsg("IP address and mask do not match"),
1113 errcontext("line %d of configuration file \"%s\"",
1114 line_num, HbaFileName)));
1121 /* Get the authentication method */
1122 field = lnext(field);
1126 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1127 errmsg("end-of-line before authentication method"),
1128 errcontext("line %d of configuration file \"%s\"",
1129 line_num, HbaFileName)));
1132 tokens = lfirst(field);
1133 if (tokens->length > 1)
1136 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1137 errmsg("multiple values specified for authentication type"),
1138 errhint("Specify exactly one authentication type per line."),
1139 errcontext("line %d of configuration file \"%s\"",
1140 line_num, HbaFileName)));
1143 token = linitial(tokens);
1146 if (strcmp(token->string, "trust") == 0)
1147 parsedline->auth_method = uaTrust;
1148 else if (strcmp(token->string, "ident") == 0)
1149 parsedline->auth_method = uaIdent;
1150 else if (strcmp(token->string, "peer") == 0)
1151 parsedline->auth_method = uaPeer;
1152 else if (strcmp(token->string, "password") == 0)
1153 parsedline->auth_method = uaPassword;
1154 else if (strcmp(token->string, "krb5") == 0)
1156 parsedline->auth_method = uaKrb5;
1160 else if (strcmp(token->string, "gss") == 0)
1162 parsedline->auth_method = uaGSS;
1166 else if (strcmp(token->string, "sspi") == 0)
1168 parsedline->auth_method = uaSSPI;
1172 else if (strcmp(token->string, "reject") == 0)
1173 parsedline->auth_method = uaReject;
1174 else if (strcmp(token->string, "md5") == 0)
1176 if (Db_user_namespace)
1179 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1180 errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled"),
1181 errcontext("line %d of configuration file \"%s\"",
1182 line_num, HbaFileName)));
1185 parsedline->auth_method = uaMD5;
1187 else if (strcmp(token->string, "pam") == 0)
1189 parsedline->auth_method = uaPAM;
1193 else if (strcmp(token->string, "ldap") == 0)
1195 parsedline->auth_method = uaLDAP;
1199 else if (strcmp(token->string, "cert") == 0)
1201 parsedline->auth_method = uaCert;
1205 else if (strcmp(token->string, "radius") == 0)
1206 parsedline->auth_method = uaRADIUS;
1210 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1211 errmsg("invalid authentication method \"%s\"",
1213 errcontext("line %d of configuration file \"%s\"",
1214 line_num, HbaFileName)));
1221 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1222 errmsg("invalid authentication method \"%s\": not supported by this build",
1224 errcontext("line %d of configuration file \"%s\"",
1225 line_num, HbaFileName)));
1230 * XXX: When using ident on local connections, change it to peer, for
1231 * backwards compatibility.
1233 if (parsedline->conntype == ctLocal &&
1234 parsedline->auth_method == uaIdent)
1235 parsedline->auth_method = uaPeer;
1237 /* Invalid authentication combinations */
1238 if (parsedline->conntype == ctLocal &&
1239 parsedline->auth_method == uaKrb5)
1242 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1243 errmsg("krb5 authentication is not supported on local sockets"),
1244 errcontext("line %d of configuration file \"%s\"",
1245 line_num, HbaFileName)));
1249 if (parsedline->conntype == ctLocal &&
1250 parsedline->auth_method == uaGSS)
1253 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1254 errmsg("gssapi authentication is not supported on local sockets"),
1255 errcontext("line %d of configuration file \"%s\"",
1256 line_num, HbaFileName)));
1260 if (parsedline->conntype != ctLocal &&
1261 parsedline->auth_method == uaPeer)
1264 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1265 errmsg("peer authentication is only supported on local sockets"),
1266 errcontext("line %d of configuration file \"%s\"",
1267 line_num, HbaFileName)));
1272 * SSPI authentication can never be enabled on ctLocal connections,
1273 * because it's only supported on Windows, where ctLocal isn't supported.
1277 if (parsedline->conntype != ctHostSSL &&
1278 parsedline->auth_method == uaCert)
1281 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1282 errmsg("cert authentication is only supported on hostssl connections"),
1283 errcontext("line %d of configuration file \"%s\"",
1284 line_num, HbaFileName)));
1288 /* Parse remaining arguments */
1289 while ((field = lnext(field)) != NULL)
1291 tokens = lfirst(field);
1292 foreach(tokencell, tokens)
1296 token = lfirst(tokencell);
1298 str = pstrdup(token->string);
1299 val = strchr(str, '=');
1303 * Got something that's not a name=value pair.
1306 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1307 errmsg("authentication option not in name=value format: %s", token->string),
1308 errcontext("line %d of configuration file \"%s\"",
1309 line_num, HbaFileName)));
1313 *val++ = '\0'; /* str now holds "name", val holds "value" */
1314 if (!parse_hba_auth_opt(str, val, parsedline, line_num))
1315 /* parse_hba_auth_opt already logged the error message */
1322 * Check if the selected authentication method has any mandatory arguments
1325 if (parsedline->auth_method == uaLDAP)
1327 MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
1330 * LDAP can operate in two modes: either with a direct bind, using
1331 * ldapprefix and ldapsuffix, or using a search+bind, using
1332 * ldapbasedn, ldapbinddn, ldapbindpasswd and ldapsearchattribute.
1333 * Disallow mixing these parameters.
1335 if (parsedline->ldapprefix || parsedline->ldapsuffix)
1337 if (parsedline->ldapbasedn ||
1338 parsedline->ldapbinddn ||
1339 parsedline->ldapbindpasswd ||
1340 parsedline->ldapsearchattribute)
1343 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1344 errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, or ldapsearchattribute together with ldapprefix"),
1345 errcontext("line %d of configuration file \"%s\"",
1346 line_num, HbaFileName)));
1350 else if (!parsedline->ldapbasedn)
1353 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1354 errmsg("authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"),
1355 errcontext("line %d of configuration file \"%s\"",
1356 line_num, HbaFileName)));
1361 if (parsedline->auth_method == uaRADIUS)
1363 MANDATORY_AUTH_ARG(parsedline->radiusserver, "radiusserver", "radius");
1364 MANDATORY_AUTH_ARG(parsedline->radiussecret, "radiussecret", "radius");
1368 * Enforce any parameters implied by other settings.
1370 if (parsedline->auth_method == uaCert)
1372 parsedline->clientcert = true;
1379 * Parse one name-value pair as an authentication option into the given
1380 * HbaLine. Return true if we successfully parse the option, false if we
1381 * encounter an error.
1384 parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
1386 if (strcmp(name, "map") == 0)
1388 if (hbaline->auth_method != uaIdent &&
1389 hbaline->auth_method != uaPeer &&
1390 hbaline->auth_method != uaKrb5 &&
1391 hbaline->auth_method != uaGSS &&
1392 hbaline->auth_method != uaSSPI &&
1393 hbaline->auth_method != uaCert)
1394 INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, krb5, gssapi, sspi, and cert"));
1395 hbaline->usermap = pstrdup(val);
1397 else if (strcmp(name, "clientcert") == 0)
1400 * Since we require ctHostSSL, this really can never happen on
1401 * non-SSL-enabled builds, so don't bother checking for USE_SSL.
1403 if (hbaline->conntype != ctHostSSL)
1406 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1407 errmsg("clientcert can only be configured for \"hostssl\" rows"),
1408 errcontext("line %d of configuration file \"%s\"",
1409 line_num, HbaFileName)));
1412 if (strcmp(val, "1") == 0)
1414 if (!secure_loaded_verify_locations())
1417 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1418 errmsg("client certificates can only be checked if a root certificate store is available"),
1419 errhint("Make sure the configuration parameter \"ssl_ca_file\" is set."),
1420 errcontext("line %d of configuration file \"%s\"",
1421 line_num, HbaFileName)));
1424 hbaline->clientcert = true;
1428 if (hbaline->auth_method == uaCert)
1431 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1432 errmsg("clientcert can not be set to 0 when using \"cert\" authentication"),
1433 errcontext("line %d of configuration file \"%s\"",
1434 line_num, HbaFileName)));
1437 hbaline->clientcert = false;
1440 else if (strcmp(name, "pamservice") == 0)
1442 REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
1443 hbaline->pamservice = pstrdup(val);
1445 else if (strcmp(name, "ldaptls") == 0)
1447 REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
1448 if (strcmp(val, "1") == 0)
1449 hbaline->ldaptls = true;
1451 hbaline->ldaptls = false;
1453 else if (strcmp(name, "ldapserver") == 0)
1455 REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
1456 hbaline->ldapserver = pstrdup(val);
1458 else if (strcmp(name, "ldapport") == 0)
1460 REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
1461 hbaline->ldapport = atoi(val);
1462 if (hbaline->ldapport == 0)
1465 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1466 errmsg("invalid LDAP port number: \"%s\"", val),
1467 errcontext("line %d of configuration file \"%s\"",
1468 line_num, HbaFileName)));
1472 else if (strcmp(name, "ldapbinddn") == 0)
1474 REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
1475 hbaline->ldapbinddn = pstrdup(val);
1477 else if (strcmp(name, "ldapbindpasswd") == 0)
1479 REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
1480 hbaline->ldapbindpasswd = pstrdup(val);
1482 else if (strcmp(name, "ldapsearchattribute") == 0)
1484 REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
1485 hbaline->ldapsearchattribute = pstrdup(val);
1487 else if (strcmp(name, "ldapbasedn") == 0)
1489 REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
1490 hbaline->ldapbasedn = pstrdup(val);
1492 else if (strcmp(name, "ldapprefix") == 0)
1494 REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
1495 hbaline->ldapprefix = pstrdup(val);
1497 else if (strcmp(name, "ldapsuffix") == 0)
1499 REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
1500 hbaline->ldapsuffix = pstrdup(val);
1502 else if (strcmp(name, "krb_server_hostname") == 0)
1504 REQUIRE_AUTH_OPTION(uaKrb5, "krb_server_hostname", "krb5");
1505 hbaline->krb_server_hostname = pstrdup(val);
1507 else if (strcmp(name, "krb_realm") == 0)
1509 if (hbaline->auth_method != uaKrb5 &&
1510 hbaline->auth_method != uaGSS &&
1511 hbaline->auth_method != uaSSPI)
1512 INVALID_AUTH_OPTION("krb_realm", gettext_noop("krb5, gssapi, and sspi"));
1513 hbaline->krb_realm = pstrdup(val);
1515 else if (strcmp(name, "include_realm") == 0)
1517 if (hbaline->auth_method != uaKrb5 &&
1518 hbaline->auth_method != uaGSS &&
1519 hbaline->auth_method != uaSSPI)
1520 INVALID_AUTH_OPTION("include_realm", gettext_noop("krb5, gssapi, and sspi"));
1521 if (strcmp(val, "1") == 0)
1522 hbaline->include_realm = true;
1524 hbaline->include_realm = false;
1526 else if (strcmp(name, "radiusserver") == 0)
1528 struct addrinfo *gai_result;
1529 struct addrinfo hints;
1532 REQUIRE_AUTH_OPTION(uaRADIUS, "radiusserver", "radius");
1534 MemSet(&hints, 0, sizeof(hints));
1535 hints.ai_socktype = SOCK_DGRAM;
1536 hints.ai_family = AF_UNSPEC;
1538 ret = pg_getaddrinfo_all(val, NULL, &hints, &gai_result);
1539 if (ret || !gai_result)
1542 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1543 errmsg("could not translate RADIUS server name \"%s\" to address: %s",
1544 val, gai_strerror(ret)),
1545 errcontext("line %d of configuration file \"%s\"",
1546 line_num, HbaFileName)));
1548 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1551 pg_freeaddrinfo_all(hints.ai_family, gai_result);
1552 hbaline->radiusserver = pstrdup(val);
1554 else if (strcmp(name, "radiusport") == 0)
1556 REQUIRE_AUTH_OPTION(uaRADIUS, "radiusport", "radius");
1557 hbaline->radiusport = atoi(val);
1558 if (hbaline->radiusport == 0)
1561 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1562 errmsg("invalid RADIUS port number: \"%s\"", val),
1563 errcontext("line %d of configuration file \"%s\"",
1564 line_num, HbaFileName)));
1568 else if (strcmp(name, "radiussecret") == 0)
1570 REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecret", "radius");
1571 hbaline->radiussecret = pstrdup(val);
1573 else if (strcmp(name, "radiusidentifier") == 0)
1575 REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifier", "radius");
1576 hbaline->radiusidentifier = pstrdup(val);
1581 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1582 errmsg("unrecognized authentication option name: \"%s\"",
1584 errcontext("line %d of configuration file \"%s\"",
1585 line_num, HbaFileName)));
1592 * Scan the pre-parsed hba file, looking for a match to the port's connection
1596 check_hba(hbaPort *port)
1602 /* Get the target role's OID. Note we do not error out for bad role. */
1603 roleid = get_role_oid(port->user_name, true);
1605 foreach(line, parsed_hba_lines)
1607 hba = (HbaLine *) lfirst(line);
1609 /* Check connection type */
1610 if (hba->conntype == ctLocal)
1612 if (!IS_AF_UNIX(port->raddr.addr.ss_family))
1617 if (IS_AF_UNIX(port->raddr.addr.ss_family))
1620 /* Check SSL state */
1624 /* Connection is SSL, match both "host" and "hostssl" */
1625 if (hba->conntype == ctHostNoSSL)
1630 /* Connection is not SSL, match both "host" and "hostnossl" */
1631 if (hba->conntype == ctHostSSL)
1635 /* No SSL support, so reject "hostssl" lines */
1636 if (hba->conntype == ctHostSSL)
1640 /* Check IP address */
1641 switch (hba->ip_cmp_method)
1646 if (!check_hostname(port,
1652 if (!check_ip(&port->raddr,
1653 (struct sockaddr *) & hba->addr,
1654 (struct sockaddr *) & hba->mask))
1662 if (!check_same_host_or_net(&port->raddr,
1663 hba->ip_cmp_method))
1667 /* shouldn't get here, but deem it no-match if so */
1672 /* Check database and role */
1673 if (!check_db(port->database_name, port->user_name, roleid,
1677 if (!check_role(port->user_name, roleid, hba->roles))
1680 /* Found a record that matched! */
1685 /* If no matching entry was found, then implicitly reject. */
1686 hba = palloc0(sizeof(HbaLine));
1687 hba->auth_method = uaImplicitReject;
1692 * Read the config file and create a List of HbaLine records for the contents.
1694 * The configuration is read into a temporary list, and if any parse error
1695 * occurs the old list is kept in place and false is returned. Only if the
1696 * whole file parses OK is the list replaced, and the function returns true.
1698 * On a false result, caller will take care of reporting a FATAL error in case
1699 * this is the initial startup. If it happens on reload, we just keep running
1700 * with the old data.
1706 List *hba_lines = NIL;
1707 List *hba_line_nums = NIL;
1710 List *new_parsed_lines = NIL;
1712 MemoryContext linecxt;
1713 MemoryContext oldcxt;
1714 MemoryContext hbacxt;
1716 file = AllocateFile(HbaFileName, "r");
1720 (errcode_for_file_access(),
1721 errmsg("could not open configuration file \"%s\": %m",
1726 linecxt = tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums);
1729 /* Now parse all the lines */
1730 hbacxt = AllocSetContextCreate(TopMemoryContext,
1731 "hba parser context",
1732 ALLOCSET_DEFAULT_MINSIZE,
1733 ALLOCSET_DEFAULT_MINSIZE,
1734 ALLOCSET_DEFAULT_MAXSIZE);
1735 oldcxt = MemoryContextSwitchTo(hbacxt);
1736 forboth(line, hba_lines, line_num, hba_line_nums)
1740 if ((newline = parse_hba_line(lfirst(line), lfirst_int(line_num))) == NULL)
1743 * Parse error in the file, so indicate there's a problem. NB: a
1744 * problem in a line will free the memory for all previous lines
1747 MemoryContextReset(hbacxt);
1748 new_parsed_lines = NIL;
1752 * Keep parsing the rest of the file so we can report errors on
1753 * more than the first row. Error has already been reported in the
1754 * parsing function, so no need to log it here.
1759 new_parsed_lines = lappend(new_parsed_lines, newline);
1763 * A valid HBA file must have at least one entry; else there's no way to
1764 * connect to the postmaster. But only complain about this if we didn't
1765 * already have parsing errors.
1767 if (ok && new_parsed_lines == NIL)
1770 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1771 errmsg("configuration file \"%s\" contains no entries",
1776 /* Free tokenizer memory */
1777 MemoryContextDelete(linecxt);
1778 MemoryContextSwitchTo(oldcxt);
1782 /* File contained one or more errors, so bail out */
1783 MemoryContextDelete(hbacxt);
1787 /* Loaded new file successfully, replace the one we use */
1788 if (parsed_hba_context != NULL)
1789 MemoryContextDelete(parsed_hba_context);
1790 parsed_hba_context = hbacxt;
1791 parsed_hba_lines = new_parsed_lines;
1797 * Process one line from the ident config file.
1799 * Take the line and compare it to the needed map, pg_role and ident_user.
1800 * *found_p and *error_p are set according to our results.
1803 parse_ident_usermap(List *line, int line_number, const char *usermap_name,
1804 const char *pg_role, const char *ident_user,
1805 bool case_insensitive, bool *found_p, bool *error_p)
1812 char *file_ident_user;
1817 Assert(line != NIL);
1818 field = list_head(line);
1820 /* Get the map token (must exist) */
1821 tokens = lfirst(field);
1822 IDENT_MULTI_VALUE(tokens);
1823 token = linitial(tokens);
1824 file_map = token->string;
1826 /* Get the ident user token */
1827 field = lnext(field);
1828 IDENT_FIELD_ABSENT(field);
1829 tokens = lfirst(field);
1830 IDENT_MULTI_VALUE(tokens);
1831 token = linitial(tokens);
1832 file_ident_user = token->string;
1834 /* Get the PG rolename token */
1835 field = lnext(field);
1836 IDENT_FIELD_ABSENT(field);
1837 tokens = lfirst(field);
1838 IDENT_MULTI_VALUE(tokens);
1839 token = linitial(tokens);
1840 file_pgrole = token->string;
1842 if (strcmp(file_map, usermap_name) != 0)
1843 /* Line does not match the map name we're looking for, so just abort */
1847 if (file_ident_user[0] == '/')
1850 * When system username starts with a slash, treat it as a regular
1851 * expression. In this case, we process the system username as a
1852 * regular expression that returns exactly one match. This is replaced
1853 * for \1 in the database username string, if present.
1857 regmatch_t matches[2];
1861 char *regexp_pgrole;
1863 wstr = palloc((strlen(file_ident_user + 1) + 1) * sizeof(pg_wchar));
1864 wlen = pg_mb2wchar_with_len(file_ident_user + 1, wstr, strlen(file_ident_user + 1));
1867 * XXX: Major room for optimization: regexps could be compiled when
1868 * the file is loaded and then re-used in every connection.
1870 r = pg_regcomp(&re, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
1875 pg_regerror(r, &re, errstr, sizeof(errstr));
1877 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1878 errmsg("invalid regular expression \"%s\": %s",
1879 file_ident_user + 1, errstr)));
1887 wstr = palloc((strlen(ident_user) + 1) * sizeof(pg_wchar));
1888 wlen = pg_mb2wchar_with_len(ident_user, wstr, strlen(ident_user));
1890 r = pg_regexec(&re, wstr, wlen, 0, NULL, 2, matches, 0);
1895 if (r != REG_NOMATCH)
1897 /* REG_NOMATCH is not an error, everything else is */
1898 pg_regerror(r, &re, errstr, sizeof(errstr));
1900 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1901 errmsg("regular expression match for \"%s\" failed: %s",
1902 file_ident_user + 1, errstr)));
1912 if ((ofs = strstr(file_pgrole, "\\1")) != NULL)
1914 /* substitution of the first argument requested */
1915 if (matches[1].rm_so < 0)
1918 (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1919 errmsg("regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"",
1920 file_ident_user + 1, file_pgrole)));
1927 * length: original length minus length of \1 plus length of match
1928 * plus null terminator
1930 regexp_pgrole = palloc0(strlen(file_pgrole) - 2 + (matches[1].rm_eo - matches[1].rm_so) + 1);
1931 strncpy(regexp_pgrole, file_pgrole, (ofs - file_pgrole));
1932 memcpy(regexp_pgrole + strlen(regexp_pgrole),
1933 ident_user + matches[1].rm_so,
1934 matches[1].rm_eo - matches[1].rm_so);
1935 strcat(regexp_pgrole, ofs + 2);
1939 /* no substitution, so copy the match */
1940 regexp_pgrole = pstrdup(file_pgrole);
1946 * now check if the username actually matched what the user is trying
1949 if (case_insensitive)
1951 if (pg_strcasecmp(regexp_pgrole, pg_role) == 0)
1956 if (strcmp(regexp_pgrole, pg_role) == 0)
1959 pfree(regexp_pgrole);
1965 /* Not regular expression, so make complete match */
1966 if (case_insensitive)
1968 if (pg_strcasecmp(file_pgrole, pg_role) == 0 &&
1969 pg_strcasecmp(file_ident_user, ident_user) == 0)
1974 if (strcmp(file_pgrole, pg_role) == 0 &&
1975 strcmp(file_ident_user, ident_user) == 0)
1984 * Scan the (pre-parsed) ident usermap file line by line, looking for a match
1986 * See if the user with ident username "auth_user" is allowed to act
1987 * as Postgres user "pg_role" according to usermap "usermap_name".
1989 * Special case: Usermap NULL, equivalent to what was previously called
1990 * "sameuser" or "samerole", means don't look in the usermap file.
1991 * That's an implied map wherein "pg_role" must be identical to
1992 * "auth_user" in order to be authorized.
1994 * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
1997 check_usermap(const char *usermap_name,
1998 const char *pg_role,
1999 const char *auth_user,
2000 bool case_insensitive)
2002 bool found_entry = false,
2005 if (usermap_name == NULL || usermap_name[0] == '\0')
2007 if (case_insensitive)
2009 if (pg_strcasecmp(pg_role, auth_user) == 0)
2014 if (strcmp(pg_role, auth_user) == 0)
2018 (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2019 pg_role, auth_user)));
2020 return STATUS_ERROR;
2024 ListCell *line_cell,
2027 forboth(line_cell, ident_lines, num_cell, ident_line_nums)
2029 parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
2030 usermap_name, pg_role, auth_user, case_insensitive,
2031 &found_entry, &error);
2032 if (found_entry || error)
2036 if (!found_entry && !error)
2039 (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
2040 usermap_name, pg_role, auth_user)));
2042 return found_entry ? STATUS_OK : STATUS_ERROR;
2047 * Read the ident config file and populate ident_lines and ident_line_nums.
2049 * Like parsed_hba_lines, ident_lines is a triple-nested List of lines, fields
2057 if (ident_context != NULL)
2059 MemoryContextDelete(ident_context);
2060 ident_context = NULL;
2063 file = AllocateFile(IdentFileName, "r");
2066 /* not fatal ... we just won't do any special ident maps */
2068 (errcode_for_file_access(),
2069 errmsg("could not open usermap file \"%s\": %m",
2074 ident_context = tokenize_file(IdentFileName, file, &ident_lines,
2083 * Determine what authentication method should be used when accessing database
2084 * "database" from frontend "raddr", user "user". Return the method and
2085 * an optional argument (stored in fields of *port), and STATUS_OK.
2087 * If the file does not contain any entry matching the request, we return
2088 * method = uaImplicitReject.
2091 hba_getauthmethod(hbaPort *port)