hba.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,584 行 · 第 1/3 页
C
1,584 行
else *error_p = true; line = lnext(line); } if (!*error_p) { /* Get the authentication argument token, if any */ if (line) { token = lfirst(line); *auth_arg_p = pstrdup(token); /* If there is more on the line, it is an error */ if (lnext(line)) *error_p = true; } }}/* * Process one line from the hba config file. * * See if it applies to a connection from a host with IP address port->raddr * to a database named port->database. If so, return *found_p true * and fill in the auth arguments into the appropriate port fields. * If not, leave *found_p as it was. If the record has a syntax error, * return *error_p true, after issuing a message to the log. If no error, * leave *error_p as it was. */static voidparse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p){ int line_number; char *token; char *db; char *user; struct addrinfo *gai_result; struct addrinfo hints; int ret; struct sockaddr_storage addr; struct sockaddr_storage mask; char *cidr_slash; Assert(line != NIL); line_number = lfirsti(line); line = lnext(line); Assert(line != NIL); /* Check the record type. */ token = lfirst(line); if (strcmp(token, "local") == 0) { /* Get the database. */ line = lnext(line); if (!line) goto hba_syntax; db = lfirst(line); /* Get the user. */ line = lnext(line); if (!line) goto hba_syntax; user = lfirst(line); line = lnext(line); if (!line) goto hba_syntax; /* Read the rest of the line. */ parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p); if (*error_p) goto hba_syntax; /* Disallow auth methods that always need TCP/IP sockets to work */ if (port->auth_method == uaKrb4 || port->auth_method == uaKrb5) goto hba_syntax; /* Does not match if connection isn't AF_UNIX */ if (!IS_AF_UNIX(port->raddr.addr.ss_family)) return; } else if (strcmp(token, "host") == 0 || strcmp(token, "hostssl") == 0 || strcmp(token, "hostnossl") == 0) { if (token[4] == 's') /* "hostssl" */ {#ifdef USE_SSL /* Record does not match if we are not on an SSL connection */ if (!port->ssl) return; /* Placeholder to require specific SSL level, perhaps? */ /* Or a client certificate */ /* Since we were on SSL, proceed as with normal 'host' mode */#else /* We don't accept this keyword at all if no SSL support */ goto hba_syntax;#endif }#ifdef USE_SSL else if (token[4] == 'n') /* "hostnossl" */ { /* Record does not match if we are on an SSL connection */ if (port->ssl) return; }#endif /* Get the database. */ line = lnext(line); if (!line) goto hba_syntax; db = lfirst(line); /* Get the user. */ line = lnext(line); if (!line) goto hba_syntax; user = lfirst(line); /* Read the IP address field. (with or without CIDR netmask) */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); /* Check if it has a CIDR suffix and if so isolate it */ cidr_slash = strchr(token, '/'); if (cidr_slash) *cidr_slash = '\0'; /* Get the IP address either way */ hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_UNSPEC; hints.ai_socktype = 0; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; ret = getaddrinfo_all(token, NULL, &hints, &gai_result); if (ret || !gai_result) { ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid IP address \"%s\" in pg_hba.conf file: %s", token, gai_strerror(ret)))); if (cidr_slash) *cidr_slash = '/'; if (gai_result) freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; } if (cidr_slash) *cidr_slash = '/'; memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen); freeaddrinfo_all(hints.ai_family, gai_result); /* Get the netmask */ if (cidr_slash) { if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0) goto hba_syntax; } else { /* Read the mask field. */ line = lnext(line); if (!line) goto hba_syntax; token = lfirst(line); ret = getaddrinfo_all(token, NULL, &hints, &gai_result); if (ret || !gai_result) { if (gai_result) freeaddrinfo_all(hints.ai_family, gai_result); goto hba_syntax; } memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen); freeaddrinfo_all(hints.ai_family, gai_result); if (addr.ss_family != mask.ss_family) goto hba_syntax; } if (addr.ss_family != port->raddr.addr.ss_family) { /* * Wrong address family. We allow only one case: if the * file has IPv4 and the port is IPv6, promote the file * address to IPv6 and try to match that way. */#ifdef HAVE_IPV6 if (addr.ss_family == AF_INET && port->raddr.addr.ss_family == AF_INET6) { promote_v4_to_v6_addr(&addr); promote_v4_to_v6_mask(&mask); } else#endif /* HAVE_IPV6 */ { /* Line doesn't match client port, so ignore it. */ return; } } /* Ignore line if client port is not in the matching addr range. */ if (!rangeSockAddr(&port->raddr.addr, &addr, &mask)) return; /* Read the rest of the line. */ line = lnext(line); if (!line) goto hba_syntax; parse_hba_auth(line, &port->auth_method, &port->auth_arg, error_p); if (*error_p) goto hba_syntax; } else goto hba_syntax; if (!check_db(port->database_name, port->user_name, db)) return; if (!check_user(port->user_name, user)) return; /* Success */ *found_p = true; return;hba_syntax: if (line) ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid entry in pg_hba.conf file at line %d, token \"%s\"", line_number, (const char *) lfirst(line)))); else ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("missing field in pg_hba.conf file at end of line %d", line_number))); *error_p = true;}/* * Scan the (pre-parsed) hba file line by line, looking for a match * to the port's connection request. */static boolcheck_hba(hbaPort *port){ bool found_entry = false; bool error = false; List *line; foreach(line, hba_lines) { parse_hba(lfirst(line), port, &found_entry, &error); if (found_entry || error) break; } if (!error) { /* If no matching entry was found, synthesize 'reject' entry. */ if (!found_entry) port->auth_method = uaReject; return true; } else return false;}/* * Open the group file if possible (return NULL if not) */static FILE *group_openfile(void){ char *filename; FILE *groupfile; filename = group_getfilename(); groupfile = AllocateFile(filename, "r"); if (groupfile == NULL && errno != ENOENT) ereport(LOG, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", filename))); pfree(filename); return groupfile;}/* * Open the password file if possible (return NULL if not) */static FILE *user_openfile(void){ char *filename; FILE *pwdfile; filename = user_getfilename(); pwdfile = AllocateFile(filename, "r"); if (pwdfile == NULL && errno != ENOENT) ereport(LOG, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", filename))); pfree(filename); return pwdfile;}/* * Load group/user name mapping file */voidload_group(void){ FILE *group_file; List *line; /* Discard any old data */ if (group_lines) free_lines(&group_lines); if (group_sorted) pfree(group_sorted); group_sorted = NULL; group_length = 0; group_file = group_openfile(); if (!group_file) return; group_lines = tokenize_file(group_file); FreeFile(group_file); /* create sorted lines for binary searching */ group_length = length(group_lines); if (group_length) { int i = 0; group_sorted = palloc(group_length * sizeof(List *)); foreach(line, group_lines) group_sorted[i++] = lfirst(line); qsort((void *) group_sorted, group_length, sizeof(List *), user_group_qsort_cmp); }}/* * Load user/password mapping file */voidload_user(void){ FILE *user_file; List *line; /* Discard any old data */ if (user_lines) free_lines(&user_lines); if (user_sorted) pfree(user_sorted); user_sorted = NULL; user_length = 0; user_file = user_openfile(); if (!user_file) return; user_lines = tokenize_file(user_file); FreeFile(user_file); /* create sorted lines for binary searching */ user_length = length(user_lines); if (user_length) { int i = 0; user_sorted = palloc(user_length * sizeof(List *)); foreach(line, user_lines) user_sorted[i++] = lfirst(line); qsort((void *) user_sorted, user_length, sizeof(List *), user_group_qsort_cmp); }}/* * Read the config file and create a List of Lists of tokens in the file. * If we find a file by the old name of the config file (pg_hba), we issue * an error message because it probably needs to be converted. He didn't * follow directions and just installed his old hba file in the new database * system. */voidload_hba(void){ int bufsize; FILE *file; /* The config file we have to read */ char *conf_file; /* The name of the config file */ if (hba_lines) free_lines(&hba_lines); /* Put together the full pathname to the config file. */ bufsize = (strlen(DataDir) + strlen(CONF_FILE) + 2) * sizeof(char); conf_file = (char *) palloc(bufsize); snprintf(conf_file, bufsize, "%s/%s", DataDir, CONF_FILE); file = AllocateFile(conf_file, "r"); if (file == NULL) ereport(FATAL, (errcode_for_file_access(), errmsg("could not open configuration file \"%s\": %m", conf_file))); hba_lines = tokenize_file(file); FreeFile(file); pfree(conf_file);}/* * Process one line from the ident config file. * * Take the line and compare it to the needed map, pg_user and ident_user. * *found_p and *error_p are set according to our results. */static voidparse_ident_usermap(List *line, const char *usermap_name, const char *pg_user, const char *ident_user, bool *found_p, bool *error_p){ int line_number; char *token; char *file_map; char *file_pguser; char *file_ident_user; *found_p = false; *error_p = false; Assert(line != NIL); line_number = lfirsti(line); line = lnext(line); Assert(line != NIL); /* Get the map token (must exist) */ token = lfirst(line); file_map = token; /* Get the ident user token (must be provided) */ line = lnext(line); if (!line) goto ident_syntax; token = lfirst(line); file_ident_user = token; /* Get the PG username token */ line = lnext(line); if (!line) goto ident_syntax; token = lfirst(line); file_pguser = token; /* Match? */ if (strcmp(file_map, usermap_name) == 0 && strcmp(file_pguser, pg_user) == 0 && strcmp(file_ident_user, ident_user) == 0) *found_p = true; return;ident_syntax: if (line) ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("invalid entry in pg_ident.conf file at line %d, token \"%s\"", line_number, (const char *) lfirst(line)))); else ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("missing entry in pg_ident.conf file at end of line %d", line_number))); *error_p = true;}/* * Scan the (pre-parsed) ident usermap file line by line, looking for a match * * See if the user with ident username "ident_user" is allowed to act * as Postgres user "pguser" according to usermap "usermap_name". * * Special case: For usermap "sameuser", don't look in the usermap * file. That's an implied map where "pguser" must be identical to * "ident_user" in order to be authorized.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?