📄 hba.c
字号:
{ snprintf(PQerrormsg, ERROR_MSG_LENGTH, "Failed to create socket on which to talk to Ident server. " "socket() returned errno = %s (%d)\n", strerror(errno), errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); } else { struct sockaddr_in ident_server; struct sockaddr_in la; /* * Socket address of Ident server on the system from which client * is attempting to connect to us. */ ident_server.sin_family = AF_INET; ident_server.sin_port = htons(IDENT_PORT); ident_server.sin_addr = remote_ip_addr; /* * Bind to the address which the client originally contacted, * otherwise the ident server won't be able to match up the right * connection. This is necessary if the PostgreSQL server is * running on an IP alias. */ memset(&la, 0, sizeof(la)); la.sin_family = AF_INET; la.sin_addr = local_ip_addr; rc = bind(sock_fd, (struct sockaddr *) & la, sizeof(la)); if (rc == 0) { rc = connect(sock_fd, (struct sockaddr *) & ident_server, sizeof(ident_server)); } if (rc != 0) { snprintf(PQerrormsg, ERROR_MSG_LENGTH, "Unable to connect to Ident server on the host which is " "trying to connect to Postgres " "(IP address %s, Port %d). " "errno = %s (%d)\n", inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); *ident_failed = true; } else { char ident_query[80]; /* The query we send to the Ident server */ snprintf(ident_query, 80, "%d,%d\n", ntohs(remote_port), ntohs(local_port)); rc = send(sock_fd, ident_query, strlen(ident_query), 0); if (rc < 0) { snprintf(PQerrormsg, ERROR_MSG_LENGTH, "Unable to send query to Ident server on the host which is " "trying to connect to Postgres (Host %s, Port %d)," "even though we successfully connected to it. " "errno = %s (%d)\n", inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); *ident_failed = true; } else { char ident_response[80 + IDENT_USERNAME_MAX]; rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0); if (rc < 0) { snprintf(PQerrormsg, ERROR_MSG_LENGTH, "Unable to receive response from Ident server " "on the host which is " "trying to connect to Postgres (Host %s, Port %d)," "even though we successfully sent our query to it. " "errno = %s (%d)\n", inet_ntoa(remote_ip_addr), IDENT_PORT, strerror(errno), errno); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); *ident_failed = true; } else { bool error; /* response from Ident is garbage. */ ident_response[rc] = '\0'; interpret_ident_response(ident_response, &error, ident_username); *ident_failed = error; } } close(sock_fd); } }}static voidparse_map_record(FILE *file, char *file_map, char *file_pguser, char *file_iuser){/*--------------------------------------------------------------------------- Take the noncomment line which is next on file "file" and interpret it as a line in a usermap file. Specifically, return the first 3 tokens as file_map, file_iuser, and file_pguser, respectively. If there are fewer than 3 tokens, return null strings for the missing ones.---------------------------------------------------------------------------*/ char buf[MAX_TOKEN]; /* A token read from the file */ /* Set defaults in case fields not in file */ file_map[0] = '\0'; file_pguser[0] = '\0'; file_iuser[0] = '\0'; next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { strcpy(file_map, buf); next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { strcpy(file_iuser, buf); next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { strcpy(file_pguser, buf); read_through_eol(file); return; } } snprintf(PQerrormsg, ERROR_MSG_LENGTH, "Incomplete line in pg_ident: %s", file_map); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); }}static voidverify_against_open_usermap(FILE *file, const char *pguser, const char *ident_username, const char *usermap_name, bool *checks_out_p){/*-------------------------------------------------------------------------- This function does the same thing as verify_against_usermap, only with the config file already open on stream descriptor "file".---------------------------------------------------------------------------*/ bool match; /* We found a matching entry in the map * file */ bool eof; /* We've reached the end of the file we're * reading */ match = false; /* initial value */ eof = false; /* initial value */ while (!eof && !match) { /* Process a line from the map file */ int c; /* a character read from the file */ c = getc(file); ungetc(c, file); if (c == EOF) eof = true; else { if (c == '#') read_through_eol(file); else { /* The following are fields read from a record of the file */ char file_map[MAX_TOKEN + 1]; char file_pguser[MAX_TOKEN + 1]; char file_iuser[MAX_TOKEN + 1]; parse_map_record(file, file_map, file_pguser, file_iuser); if (strcmp(file_map, usermap_name) == 0 && strcmp(file_pguser, pguser) == 0 && strcmp(file_iuser, ident_username) == 0) match = true; } } } *checks_out_p = match;}static voidverify_against_usermap(const char *pguser, const char *ident_username, const char *usermap_name, bool *checks_out_p){/*-------------------------------------------------------------------------- See if the user with ident username "ident_username" is allowed to act as Postgres user "pguser" according to usermap "usermap_name". Look it up in the usermap file. Special case: For usermap "sameuser", don't look in the usermap file. That's an implied map where "pguser" must be identical to "ident_username" in order to be authorized. Iff authorized, return *checks_out_p == true.--------------------------------------------------------------------------*/ if (usermap_name[0] == '\0') { *checks_out_p = false; snprintf(PQerrormsg, ERROR_MSG_LENGTH, "verify_against_usermap: hba configuration file does not " "have the usermap field filled in in the entry that pertains " "to this connection. That field is essential for Ident-based " "authentication.\n"); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); } else if (strcmp(usermap_name, "sameuser") == 0) { if (strcmp(ident_username, pguser) == 0) *checks_out_p = true; else *checks_out_p = false; } else { FILE *file; /* The map file we have to read */ char *map_file; /* The name of the map file we have to * read */ int bufsize; /* put together the full pathname to the map file */ bufsize = (strlen(DataDir) + strlen(USERMAP_FILE) + 2) * sizeof(char); map_file = (char *) palloc(bufsize); snprintf(map_file, bufsize, "%s/%s", DataDir, USERMAP_FILE);#ifndef __CYGWIN32__ file = AllocateFile(map_file, "r");#else file = AllocateFile(map_file, "rb");#endif if (file == NULL) { /* The open of the map file failed. */ *checks_out_p = false; snprintf(PQerrormsg, ERROR_MSG_LENGTH, "verify_against_usermap: usermap file for Ident-based " "authentication " "does not exist or permissions are not setup correctly! " "Unable to open file \"%s\".\n", map_file); fputs(PQerrormsg, stderr); pqdebug("%s", PQerrormsg); } else { verify_against_open_usermap(file, pguser, ident_username, usermap_name, checks_out_p); FreeFile(file); } pfree(map_file); }}intauthident(struct sockaddr_in * raddr, struct sockaddr_in * laddr, const char *postgres_username, const char *auth_arg){/*--------------------------------------------------------------------------- Talk to the ident server on the remote host and find out who owns the connection described by "port". Then look in the usermap file under the usermap *auth_arg and see if that user is equivalent to Postgres user *user. Return STATUS_OK if yes.---------------------------------------------------------------------------*/ bool checks_out; bool ident_failed; /* We were unable to get ident to give us a username */ char ident_username[IDENT_USERNAME_MAX + 1]; /* The username returned by ident */ ident(raddr->sin_addr, laddr->sin_addr, raddr->sin_port, laddr->sin_port, &ident_failed, ident_username); if (ident_failed) return STATUS_ERROR; verify_against_usermap(postgres_username, ident_username, auth_arg, &checks_out); return checks_out ? STATUS_OK : STATUS_ERROR;}#ifdef CYR_RECODE#define CHARSET_FILE "charset.conf"#define MAX_CHARSETS 10#define KEY_HOST 1#define KEY_BASE 2#define KEY_TABLE 3struct CharsetItem{ char Orig[MAX_TOKEN]; char Dest[MAX_TOKEN]; char Table[MAX_TOKEN];};intInRange(char *buf, int host){ int valid, i, FromAddr, ToAddr, tmp; struct in_addr file_ip_addr; char *p; unsigned int one = 0x80000000, NetMask = 0; unsigned char mask; p = strchr(buf, '/'); if (p) { *p++ = '\0'; valid = inet_aton(buf, &file_ip_addr); if (valid) { mask = strtoul(p, 0, 0); FromAddr = ntohl(file_ip_addr.s_addr); ToAddr = ntohl(file_ip_addr.s_addr); for (i = 0; i < mask; i++) { NetMask |= one; one >>= 1; } FromAddr &= NetMask; ToAddr = ToAddr | ~NetMask; tmp = ntohl(host); return ((unsigned) tmp >= (unsigned) FromAddr && (unsigned) tmp <= (unsigned) ToAddr); } } else { p = strchr(buf, '-'); if (p) { *p++ = '\0'; valid = inet_aton(buf, &file_ip_addr); if (valid) { FromAddr = ntohl(file_ip_addr.s_addr); valid = inet_aton(p, &file_ip_addr); if (valid) { ToAddr = ntohl(file_ip_addr.s_addr); tmp = ntohl(host); return ((unsigned) tmp >= (unsigned) FromAddr && (unsigned) tmp <= (unsigned) ToAddr); } } } else { valid = inet_aton(buf, &file_ip_addr); if (valid) { FromAddr = file_ip_addr.s_addr; return (unsigned) FromAddr == (unsigned) host; } } } return false;}voidGetCharSetByHost(char *TableName, int host, const char *DataDir){ FILE *file; char buf[MAX_TOKEN], BaseCharset[MAX_TOKEN], OrigCharset[MAX_TOKEN], DestCharset[MAX_TOKEN], HostCharset[MAX_TOKEN], c, eof = false, *map_file; int key = 0, ChIndex = 0, i, bufsize; struct CharsetItem *ChArray[MAX_CHARSETS]; *TableName = '\0'; bufsize = (strlen(DataDir) + strlen(CHARSET_FILE) + 2) * sizeof(char); map_file = (char *) palloc(bufsize); snprintf(map_file, bufsize, "%s/%s", DataDir, CHARSET_FILE);#ifndef __CYGWIN32__ file = AllocateFile(map_file, "r");#else file = AllocateFile(map_file, "rb");#endif if (file == NULL) return; while (!eof) { c = getc(file); ungetc(c, file); if (c == EOF) eof = true; else { if (c == '#') read_through_eol(file); else { /* Read the key */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { if (strcasecmp(buf, "HostCharset") == 0) key = KEY_HOST; if (strcasecmp(buf, "BaseCharset") == 0) key = KEY_BASE; if (strcasecmp(buf, "RecodeTable") == 0) key = KEY_TABLE; switch (key) { case KEY_HOST: /* Read the host */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { if (InRange(buf, host)) { /* Read the charset */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') strcpy(HostCharset, buf); } } break; case KEY_BASE: /* Read the base charset */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') strcpy(BaseCharset, buf); break; case KEY_TABLE: /* Read the original charset */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { strcpy(OrigCharset, buf); /* Read the destination charset */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { strcpy(DestCharset, buf); /* Read the table filename */ next_token(file, buf, sizeof(buf)); if (buf[0] != '\0') { ChArray[ChIndex] = (struct CharsetItem *) palloc(sizeof(struct CharsetItem)); strcpy(ChArray[ChIndex]->Orig, OrigCharset); strcpy(ChArray[ChIndex]->Dest, DestCharset); strcpy(ChArray[ChIndex]->Table, buf); ChIndex++; } } } break; } read_through_eol(file); } } } } FreeFile(file); pfree(map_file); for (i = 0; i < ChIndex; i++) { if (!strcasecmp(BaseCharset, ChArray[i]->Orig) && !strcasecmp(HostCharset, ChArray[i]->Dest)) strncpy(TableName, ChArray[i]->Table, 79); pfree((struct CharsetItem *) ChArray[i]); }}#endifinthba_getauthmethod(SockAddr *raddr, char *user, char *database, char *auth_arg, UserAuth *auth_method){/*--------------------------------------------------------------------------- Determine what authentication method should be used when accessing database "database" from frontend "raddr", user "user". Return the method, an optional argument, and STATUS_OK. Note that STATUS_ERROR indicates a problem with the hba config file. If the file is OK but does not contain any entry matching the request, we return STATUS_OK and method = uaReject.----------------------------------------------------------------------------*/ bool hba_ok = false; find_hba_entry(raddr, user, database, &hba_ok, auth_method, auth_arg); return hba_ok ? STATUS_OK : STATUS_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -