13
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.185 2009/04/15 21:42:50 alvherre Exp $
13
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.188 2009/06/24 13:39:42 mha Exp $
15
15
*-------------------------------------------------------------------------
569
569
* Macros used to check and report on invalid configuration options.
570
570
* INVALID_AUTH_OPTION = reports when an option is specified for a method where it's
572
572
* REQUIRE_AUTH_OPTION = same as INVALID_AUTH_OPTION, except it also checks if the
573
* method is actually the one specified. Used as a shortcut when
574
* the option is only valid for one authentication method.
573
* method is actually the one specified. Used as a shortcut when
574
* the option is only valid for one authentication method.
575
575
* MANDATORY_AUTH_ARG = check if a required option is set for an authentication method,
576
* reporting error if it's not.
576
* reporting error if it's not.
578
578
#define INVALID_AUTH_OPTION(optname, validmethods) do {\
643
643
(errcode(ERRCODE_CONFIG_FILE_ERROR),
644
644
errmsg("hostssl not supported on this platform"),
645
errhint("compile with --enable-ssl to use SSL connections"),
645
errhint("compile with --enable-ssl to use SSL connections"),
646
646
errcontext("line %d of configuration file \"%s\"",
647
line_num, HbaFileName)));
647
line_num, HbaFileName)));
667
667
errmsg("invalid connection type \"%s\"",
669
669
errcontext("line %d of configuration file \"%s\"",
670
line_num, HbaFileName)));
670
line_num, HbaFileName)));
679
679
(errcode(ERRCODE_CONFIG_FILE_ERROR),
680
680
errmsg("end-of-line before database specification"),
681
681
errcontext("line %d of configuration file \"%s\"",
682
line_num, HbaFileName)));
682
line_num, HbaFileName)));
685
685
parsedline->database = pstrdup(lfirst(line_item));
692
692
(errcode(ERRCODE_CONFIG_FILE_ERROR),
693
693
errmsg("end-of-line before role specification"),
694
694
errcontext("line %d of configuration file \"%s\"",
695
line_num, HbaFileName)));
695
line_num, HbaFileName)));
698
698
parsedline->role = pstrdup(lfirst(line_item));
707
707
(errcode(ERRCODE_CONFIG_FILE_ERROR),
708
errmsg("end-of-line before ip address specification"),
708
errmsg("end-of-line before IP address specification"),
709
709
errcontext("line %d of configuration file \"%s\"",
710
line_num, HbaFileName)));
710
line_num, HbaFileName)));
713
713
token = pstrdup(lfirst(line_item));
735
735
errmsg("invalid IP address \"%s\": %s",
736
736
token, gai_strerror(ret)),
737
737
errcontext("line %d of configuration file \"%s\"",
738
line_num, HbaFileName)));
738
line_num, HbaFileName)));
740
740
*cidr_slash = '/';
760
760
errmsg("invalid CIDR mask in address \"%s\"",
762
762
errcontext("line %d of configuration file \"%s\"",
763
line_num, HbaFileName)));
763
line_num, HbaFileName)));
774
774
(errcode(ERRCODE_CONFIG_FILE_ERROR),
775
775
errmsg("end-of-line before netmask specification"),
776
776
errcontext("line %d of configuration file \"%s\"",
777
line_num, HbaFileName)));
777
line_num, HbaFileName)));
780
780
token = lfirst(line_item);
787
787
errmsg("invalid IP mask \"%s\": %s",
788
788
token, gai_strerror(ret)),
789
789
errcontext("line %d of configuration file \"%s\"",
790
line_num, HbaFileName)));
790
line_num, HbaFileName)));
792
792
pg_freeaddrinfo_all(hints.ai_family, gai_result);
815
815
(errcode(ERRCODE_CONFIG_FILE_ERROR),
816
816
errmsg("end-of-line before authentication method"),
817
817
errcontext("line %d of configuration file \"%s\"",
818
line_num, HbaFileName)));
818
line_num, HbaFileName)));
821
821
token = lfirst(line_item);
883
883
errmsg("invalid authentication method \"%s\"",
885
885
errcontext("line %d of configuration file \"%s\"",
886
line_num, HbaFileName)));
886
line_num, HbaFileName)));
894
894
errmsg("invalid authentication method \"%s\": not supported on this platform",
896
896
errcontext("line %d of configuration file \"%s\"",
897
line_num, HbaFileName)));
897
line_num, HbaFileName)));
906
906
(errcode(ERRCODE_CONFIG_FILE_ERROR),
907
errmsg("krb5 authentication is not supported on local sockets"),
907
errmsg("krb5 authentication is not supported on local sockets"),
908
908
errcontext("line %d of configuration file \"%s\"",
909
line_num, HbaFileName)));
909
line_num, HbaFileName)));
948
*c++ = '\0'; /* token now holds "name", c holds "value" */
948
*c++ = '\0'; /* token now holds "name", c holds "value" */
949
949
if (strcmp(token, "map") == 0)
951
951
if (parsedline->auth_method != uaIdent &&
959
959
else if (strcmp(token, "clientcert") == 0)
962
* Since we require ctHostSSL, this really can never happen on non-SSL-enabled
963
* builds, so don't bother checking for USE_SSL.
962
* Since we require ctHostSSL, this really can never happen on
963
* non-SSL-enabled builds, so don't bother checking for
965
966
if (parsedline->conntype != ctHostSSL)
968
969
(errcode(ERRCODE_CONFIG_FILE_ERROR),
969
970
errmsg("clientcert can only be configured for \"hostssl\" rows"),
970
errcontext("line %d of configuration file \"%s\"",
971
line_num, HbaFileName)));
971
errcontext("line %d of configuration file \"%s\"",
972
line_num, HbaFileName)));
974
975
if (strcmp(c, "1") == 0)
979
980
(errcode(ERRCODE_CONFIG_FILE_ERROR),
980
981
errmsg("client certificates can only be checked if a root certificate store is available"),
981
982
errdetail("make sure the root certificate store is present and readable"),
982
errcontext("line %d of configuration file \"%s\"",
983
line_num, HbaFileName)));
983
errcontext("line %d of configuration file \"%s\"",
984
line_num, HbaFileName)));
986
987
parsedline->clientcert = true;
993
994
(errcode(ERRCODE_CONFIG_FILE_ERROR),
994
995
errmsg("clientcert can not be set to 0 when using \"cert\" authentication"),
995
errcontext("line %d of configuration file \"%s\"",
996
line_num, HbaFileName)));
996
errcontext("line %d of configuration file \"%s\"",
997
line_num, HbaFileName)));
999
1000
parsedline->clientcert = false;
1027
1028
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1028
1029
errmsg("invalid LDAP port number: \"%s\"", c),
1029
errcontext("line %d of configuration file \"%s\"",
1030
line_num, HbaFileName)));
1030
errcontext("line %d of configuration file \"%s\"",
1031
line_num, HbaFileName)));
1071
1072
(errcode(ERRCODE_CONFIG_FILE_ERROR),
1072
errmsg("unknown authentication option name: \"%s\"", token),
1073
errmsg("unknown authentication option name: \"%s\"", token),
1073
1074
errcontext("line %d of configuration file \"%s\"",
1074
1075
line_num, HbaFileName)));
1152
1153
#ifdef HAVE_IPV6
1153
else if (hba->addr.ss_family == AF_INET &&
1154
port->raddr.addr.ss_family == AF_INET6)
1154
else if (hba->addr.ss_family == AF_INET &&
1155
port->raddr.addr.ss_family == AF_INET6)
1157
* Wrong address family. We allow only one case: if the file has
1158
* IPv4 and the port is IPv6, promote the file address to IPv6 and
1159
* try to match that way.
1158
* Wrong address family. We allow only one case: if the file
1159
* has IPv4 and the port is IPv6, promote the file address to
1160
* IPv6 and try to match that way.
1161
struct sockaddr_storage addrcopy, maskcopy;
1162
struct sockaddr_storage addrcopy,
1162
1165
memcpy(&addrcopy, &hba->addr, sizeof(addrcopy));
1163
1166
memcpy(&maskcopy, &hba->mask, sizeof(maskcopy));
1164
1167
pg_promote_v4_to_v6_addr(&addrcopy);
1165
1168
pg_promote_v4_to_v6_mask(&maskcopy);
1167
1170
if (!pg_range_sockaddr(&port->raddr.addr, &addrcopy, &maskcopy))
1170
#endif /* HAVE_IPV6 */
1173
#endif /* HAVE_IPV6 */
1172
1175
/* Wrong address family, no IPV6 */
1176
1179
/* Check database and role */
1177
1180
if (!check_db(port->database_name, port->user_name, hba->database))
1191
1194
port->hba = hba;
1195
* Return false only happens if we have a parsing error, which we can
1198
* XXX: Return false only happens if we have a parsing error, which we can
1196
1199
* no longer have (parsing now in postmaster). Consider changing API.
1304
List *hba_lines = NIL;
1305
List *hba_line_nums = NIL;
1306
ListCell *line, *line_num;
1307
List *new_parsed_lines = NIL;
1308
List *hba_lines = NIL;
1309
List *hba_line_nums = NIL;
1312
List *new_parsed_lines = NIL;
1310
1315
file = AllocateFile(HbaFileName, "r");
1311
1316
if (file == NULL)
1314
1319
(errcode_for_file_access(),
1315
1320
errmsg("could not open configuration file \"%s\": %m",
1316
1321
HbaFileName)));
1318
1324
* Caller will take care of making this a FATAL error in case this is
1319
* the initial startup. If it happens on reload, we just keep the
1320
* old version around.
1325
* the initial startup. If it happens on reload, we just keep the old
1328
1334
/* Now parse all the lines */
1329
1335
forboth(line, hba_lines, line_num, hba_line_nums)
1333
1339
newline = palloc0(sizeof(HbaLine));
1339
1345
pfree(newline);
1342
* Keep parsing the rest of the file so we can report errors
1343
* on more than the first row. Error has already been reported
1344
* in the parsing function, so no need to log it here.
1348
* Keep parsing the rest of the file so we can report errors on
1349
* more than the first row. Error has already been reported in the
1350
* parsing function, so no need to log it here.
1461
1467
if (file_ident_user[0] == '/')
1464
* When system username starts with a slash, treat it as a regular expression.
1465
* In this case, we process the system username as a regular expression that
1466
* returns exactly one match. This is replaced for \1 in the database username
1467
* string, if present.
1470
* When system username starts with a slash, treat it as a regular
1471
* expression. In this case, we process the system username as a
1472
* regular expression that returns exactly one match. This is replaced
1473
* for \1 in the database username string, if present.
1475
1481
char *regexp_pgrole;
1477
wstr = palloc((strlen(file_ident_user+1) + 1) * sizeof(pg_wchar));
1478
wlen = pg_mb2wchar_with_len(file_ident_user+1, wstr, strlen(file_ident_user+1));
1483
wstr = palloc((strlen(file_ident_user + 1) + 1) * sizeof(pg_wchar));
1484
wlen = pg_mb2wchar_with_len(file_ident_user + 1, wstr, strlen(file_ident_user + 1));
1481
* XXX: Major room for optimization: regexps could be compiled when the file is loaded
1482
* and then re-used in every connection.
1487
* XXX: Major room for optimization: regexps could be compiled when
1488
* the file is loaded and then re-used in every connection.
1484
1490
r = pg_regcomp(&re, wstr, wlen, REG_ADVANCED);
1489
1495
pg_regerror(r, &re, errstr, sizeof(errstr));
1491
1497
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1492
errmsg("invalid regular expression \"%s\": %s", file_ident_user+1, errstr)));
1498
errmsg("invalid regular expression \"%s\": %s", file_ident_user + 1, errstr)));
1495
1501
*error_p = true;
1500
1506
wstr = palloc((strlen(ident_user) + 1) * sizeof(pg_wchar));
1501
1507
wlen = pg_mb2wchar_with_len(ident_user, wstr, strlen(ident_user));
1503
r = pg_regexec(&re, wstr, wlen, 0, NULL, 2, matches,0);
1509
r = pg_regexec(&re, wstr, wlen, 0, NULL, 2, matches, 0);
1508
1514
if (r != REG_NOMATCH)
1510
1516
/* REG_NOMATCH is not an error, everything else is */
1511
1517
pg_regerror(r, &re, errstr, sizeof(errstr));
1513
1519
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1514
errmsg("regular expression match for \"%s\" failed: %s", file_ident_user+1, errstr)));
1520
errmsg("regular expression match for \"%s\" failed: %s", file_ident_user + 1, errstr)));
1515
1521
*error_p = true;
1526
1532
/* substitution of the first argument requested */
1527
1533
if (matches[1].rm_so < 0)
1529
1536
(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
1530
1537
errmsg("regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"",
1531
file_ident_user+1, file_pgrole)));
1532
/* length: original length minus length of \1 plus length of match plus null terminator */
1533
regexp_pgrole = palloc0(strlen(file_pgrole) - 2 + (matches[1].rm_eo-matches[1].rm_so) + 1);
1534
strncpy(regexp_pgrole, file_pgrole, (ofs-file_pgrole));
1535
memcpy(regexp_pgrole+strlen(regexp_pgrole),
1536
ident_user+matches[1].rm_so,
1537
matches[1].rm_eo-matches[1].rm_so);
1538
strcat(regexp_pgrole, ofs+2);
1538
file_ident_user + 1, file_pgrole)));
1545
* length: original length minus length of \1 plus length of match
1546
* plus null terminator
1548
regexp_pgrole = palloc0(strlen(file_pgrole) - 2 + (matches[1].rm_eo - matches[1].rm_so) + 1);
1549
strncpy(regexp_pgrole, file_pgrole, (ofs - file_pgrole));
1550
memcpy(regexp_pgrole + strlen(regexp_pgrole),
1551
ident_user + matches[1].rm_so,
1552
matches[1].rm_eo - matches[1].rm_so);
1553
strcat(regexp_pgrole, ofs + 2);
1594
1612
* See if the user with ident username "ident_user" is allowed to act
1595
1613
* as Postgres user "pgrole" according to usermap "usermap_name".
1597
* Special case: Usermap NULL, equivalent to what was previously called
1598
* "sameuser" or "samerole", don't look in the usermap
1615
* Special case: Usermap NULL, equivalent to what was previously called
1616
* "sameuser" or "samerole", don't look in the usermap
1599
1617
* file. That's an implied map where "pgrole" must be identical to
1600
1618
* "ident_user" in order to be authorized.
1634
1653
forboth(line_cell, ident_lines, num_cell, ident_line_nums)
1636
1655
parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
1637
usermap_name, pg_role, auth_user, case_insensitive,
1656
usermap_name, pg_role, auth_user, case_insensitive,
1638
1657
&found_entry, &error);
1639
1658
if (found_entry || error)
1643
1662
if (!found_entry && !error)
1646
(errmsg("no match in usermap for user \"%s\" authenticated as \"%s\"",
1647
pg_role, auth_user),
1648
errcontext("usermap \"%s\"", usermap_name)));
1665
(errmsg("no match in usermap for user \"%s\" authenticated as \"%s\"",
1666
pg_role, auth_user),
1667
errcontext("usermap \"%s\"", usermap_name)));
1650
return found_entry?STATUS_OK:STATUS_ERROR;
1669
return found_entry ? STATUS_OK : STATUS_ERROR;