hba.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:28k
- /*-------------------------------------------------------------------------
- *
- * hba.c
- * Routines to handle host based authentication (that's the scheme
- * wherein you authenticate a user by seeing what IP address the system
- * says he comes from and possibly using ident).
- *
- * $Id: hba.c,v 1.43 1999/05/25 16:08:59 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <pwd.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <postgres.h>
- #include <miscadmin.h>
- #include <libpq/libpq.h>
- #include <libpq/pqcomm.h>
- #include <libpq/hba.h>
- #include <port/inet_aton.h> /* For inet_aton() */
- #include <storage/fd.h>
- /* Some standard C libraries, including GNU, have an isblank() function.
- Others, including Solaris, do not. So we have our own.
- */
- static bool
- isblank(const char c)
- {
- return c == ' ' || c == 9 /* tab */ ;
- }
- static void
- next_token(FILE *fp, char *buf, const int bufsz)
- {
- /*--------------------------------------------------------------------------
- Grab one token out of fp. Tokens are strings of non-blank
- characters bounded by blank characters, beginning of line, and end
- of line. Blank means space or tab. Return the token as *buf.
- Leave file positioned to character immediately after the token or
- EOF, whichever comes first. If no more tokens on line, return null
- string as *buf and position file to beginning of next line or EOF,
- whichever comes first.
- --------------------------------------------------------------------------*/
- int c;
- char *eb = buf + (bufsz - 1);
- /* Move over inital token-delimiting blanks */
- while (isblank(c = getc(fp)));
- if (c != 'n')
- {
- /*
- * build a token in buf of next characters up to EOF, eol, or
- * blank.
- */
- while (c != EOF && c != 'n' && !isblank(c))
- {
- if (buf < eb)
- *buf++ = c;
- c = getc(fp);
- /*
- * Put back the char right after the token (putting back EOF
- * is ok)
- */
- }
- ungetc(c, fp);
- }
- *buf = ' ';
- }
- static void
- read_through_eol(FILE *file)
- {
- int c;
- do
- c = getc(file);
- while (c != 'n' && c != EOF);
- }
- static void
- read_hba_entry2(FILE *file, UserAuth *userauth_p, char *auth_arg,
- bool *error_p)
- {
- /*--------------------------------------------------------------------------
- Read from file FILE the rest of a host record, after the mask field,
- and return the interpretation of it as *userauth_p, auth_arg, and
- *error_p.
- ---------------------------------------------------------------------------*/
- char buf[MAX_TOKEN];
- /* Get authentication type token. */
- next_token(file, buf, sizeof(buf));
- if (strcmp(buf, "trust") == 0)
- *userauth_p = uaTrust;
- else if (strcmp(buf, "ident") == 0)
- *userauth_p = uaIdent;
- else if (strcmp(buf, "password") == 0)
- *userauth_p = uaPassword;
- else if (strcmp(buf, "krb4") == 0)
- *userauth_p = uaKrb4;
- else if (strcmp(buf, "krb5") == 0)
- *userauth_p = uaKrb5;
- else if (strcmp(buf, "reject") == 0)
- *userauth_p = uaReject;
- else if (strcmp(buf, "crypt") == 0)
- *userauth_p = uaCrypt;
- else
- {
- *error_p = true;
- if (buf[0] != ' ')
- read_through_eol(file);
- }
- if (!*error_p)
- {
- /* Get the authentication argument token, if any */
- next_token(file, buf, sizeof(buf));
- if (buf[0] == ' ')
- auth_arg[0] = ' ';
- else
- {
- StrNCpy(auth_arg, buf, MAX_AUTH_ARG - 1);
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- {
- *error_p = true;
- read_through_eol(file);
- }
- }
- }
- }
- static void
- process_hba_record(FILE *file, SockAddr *raddr, const char *user,
- const char *database, bool *matches_p, bool *error_p,
- UserAuth *userauth_p, char *auth_arg)
- {
- /*---------------------------------------------------------------------------
- Process the non-comment record in the config file that is next on the file.
- See if it applies to a connection to a host with IP address "*raddr"
- to a database named "*database". If so, return *matches_p true
- and *userauth_p and *auth_arg as the values from the entry.
- If not, leave *matches_p as it was. If the record has a syntax error,
- return *error_p true, after issuing a message to stderr. If no error,
- leave *error_p as it was.
- ---------------------------------------------------------------------------*/
- char db[MAX_TOKEN],
- buf[MAX_TOKEN];
- /* Read the record type field. */
- next_token(file, buf, sizeof(buf));
- if (buf[0] == ' ')
- return;
- /* Check the record type. */
- if (strcmp(buf, "local") == 0)
- {
- /* Get the database. */
- next_token(file, db, sizeof(db));
- if (db[0] == ' ')
- goto syntax;
- /* Read the rest of the line. */
- read_hba_entry2(file, userauth_p, auth_arg, error_p);
- /*
- * For now, disallow methods that need AF_INET sockets to work.
- */
- if (!*error_p &&
- (*userauth_p == uaIdent ||
- *userauth_p == uaKrb4 ||
- *userauth_p == uaKrb5))
- *error_p = true;
- if (*error_p)
- goto syntax;
- /*
- * If this record isn't for our database, or this is the wrong
- * sort of connection, ignore it.
- */
- if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0 &&
- (strcmp(db, "sameuser") != 0 || strcmp(database, user) != 0)) ||
- raddr->sa.sa_family != AF_UNIX)
- return;
- }
- else if (strcmp(buf, "host") == 0)
- {
- struct in_addr file_ip_addr,
- mask;
- /* Get the database. */
- next_token(file, db, sizeof(db));
- if (db[0] == ' ')
- goto syntax;
- /* Read the IP address field. */
- next_token(file, buf, sizeof(buf));
- if (buf[0] == ' ')
- goto syntax;
- /* Remember the IP address field and go get mask field. */
- if (!inet_aton(buf, &file_ip_addr))
- {
- read_through_eol(file);
- goto syntax;
- }
- /* Read the mask field. */
- next_token(file, buf, sizeof(buf));
- if (buf[0] == ' ')
- goto syntax;
- if (!inet_aton(buf, &mask))
- {
- read_through_eol(file);
- goto syntax;
- }
- /*
- * This is the record we're looking for. Read the rest of the
- * info from it.
- */
- read_hba_entry2(file, userauth_p, auth_arg, error_p);
- if (*error_p)
- goto syntax;
- /*
- * If this record isn't for our database, or this is the wrong
- * sort of connection, ignore it.
- */
- if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0 &&
- (strcmp(db, "sameuser") != 0 || strcmp(database, user) != 0)) ||
- raddr->sa.sa_family != AF_INET ||
- ((file_ip_addr.s_addr ^ raddr->in.sin_addr.s_addr) & mask.s_addr) != 0x0000)
- return;
- }
- else
- {
- read_through_eol(file);
- goto syntax;
- }
- *matches_p = true;
- return;
- syntax:
- snprintf(PQerrormsg, ERROR_MSG_LENGTH,
- "process_hba_record: invalid syntax in pg_hba.conf filen");
- fputs(PQerrormsg, stderr);
- pqdebug("%s", PQerrormsg);
- *error_p = true;
- }
- static void
- process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
- const char *database, bool *hba_ok_p,
- UserAuth *userauth_p, char *auth_arg)
- {
- /*---------------------------------------------------------------------------
- This function does the same thing as find_hba_entry, only with
- the config file already open on stream descriptor "file".
- ----------------------------------------------------------------------------*/
- bool found_entry = false; /* found an applicable entry? */
- bool error = false; /* found an erroneous entry? */
- bool eof = false; /* end of hba file */
- while (!eof && !found_entry && !error)
- {
- /* Process a line from the config file */
- int c = getc(file);
- if (c == EOF)
- eof = true;
- else
- {
- ungetc(c, file);
- if (c == '#')
- read_through_eol(file);
- else
- process_hba_record(file, raddr, user, database,
- &found_entry, &error, userauth_p, auth_arg);
- }
- }
- if (!error)
- {
- /* If no matching entry was found, synthesize 'reject' entry. */
- if (!found_entry)
- *userauth_p = uaReject;
- *hba_ok_p = true;
- }
- }
- static void
- find_hba_entry(SockAddr *raddr, const char *user, const char *database,
- bool *hba_ok_p, UserAuth *userauth_p, char *auth_arg)
- {
- /*
- * Read the config file and find an entry that allows connection from
- * host "raddr", user "user", to database "database". If found,
- * return *hba_ok_p = true and *userauth_p and *auth_arg representing
- * the contents of that entry. If there is no matching entry, we
- * set *hba_ok_p = true, *userauth_p = uaReject.
- *
- * If the config file is unreadable or contains invalid syntax, we
- * issue a diagnostic message to stderr (ie, the postmaster log file)
- * and return without changing *hba_ok_p.
- *
- * 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.
- */
- int fd,
- bufsize;
- FILE *file; /* The config file we have to read */
- char *old_conf_file;
- /* The name of old config file that better not exist. */
- /* Fail if config file by old name exists. */
- /* put together the full pathname to the old config file */
- bufsize = (strlen(DataDir) + strlen(OLD_CONF_FILE) + 2) * sizeof(char);
- old_conf_file = (char *) palloc(bufsize);
- snprintf(old_conf_file, bufsize, "%s/%s", DataDir, OLD_CONF_FILE);
- #ifndef __CYGWIN32__
- if ((fd = open(old_conf_file, O_RDONLY, 0)) != -1)
- #else
- if ((fd = open(old_conf_file, O_RDONLY | O_BINARY, 0)) != -1)
- #endif
- {
- /* Old config file exists. Tell this guy he needs to upgrade. */
- close(fd);
- snprintf(PQerrormsg, ERROR_MSG_LENGTH,
- "A file exists by the name used for host-based authentication "
- "in prior releases of Postgres (%s). The name and format of "
- "the configuration file have changed, so this file should be "
- "converted.n",
- old_conf_file);
- fputs(PQerrormsg, stderr);
- pqdebug("%s", PQerrormsg);
- }
- else
- {
- char *conf_file; /* The name of the config file we have to
- * read */
- /* 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)
- {
- /* The open of the config file failed. */
- snprintf(PQerrormsg, ERROR_MSG_LENGTH,
- "find_hba_entry: Host-based authentication config file "
- "does not exist or permissions are not setup correctly! "
- "Unable to open file "%s".n",
- conf_file);
- fputs(PQerrormsg, stderr);
- pqdebug("%s", PQerrormsg);
- }
- else
- {
- process_open_config_file(file, raddr, user, database, hba_ok_p,
- userauth_p, auth_arg);
- FreeFile(file);
- }
- pfree(conf_file);
- }
- pfree(old_conf_file);
- }
- static void
- interpret_ident_response(char *ident_response,
- bool *error_p, char *ident_username)
- {
- /*----------------------------------------------------------------------------
- Parse the string "*ident_response" as a response from a query to an Ident
- server. If it's a normal response indicating a username, return
- *error_p == false and the username as *ident_username. If it's anything
- else, return *error_p == true and *ident_username undefined.
- ----------------------------------------------------------------------------*/
- char *cursor; /* Cursor into *ident_response */
- cursor = &ident_response[0];
- /*
- * Ident's response, in the telnet tradition, should end in crlf
- * (rn).
- */
- if (strlen(ident_response) < 2)
- *error_p = true;
- else if (ident_response[strlen(ident_response) - 2] != 'r')
- *error_p = true;
- else
- {
- while (*cursor != ':' && *cursor != 'r')
- cursor++; /* skip port field */
- if (*cursor != ':')
- *error_p = true;
- else
- {
- /* We're positioned to colon before response type field */
- char response_type[80];
- int i; /* Index into *response_type */
- cursor++; /* Go over colon */
- while (isblank(*cursor))
- cursor++; /* skip blanks */
- i = 0;
- while (*cursor != ':' && *cursor != 'r' && !isblank(*cursor)
- && i < sizeof(response_type) - 1)
- response_type[i++] = *cursor++;
- response_type[i] = ' ';
- while (isblank(*cursor))
- cursor++; /* skip blanks */
- if (strcmp(response_type, "USERID") != 0)
- *error_p = true;
- else
- {
- /*
- * It's a USERID response. Good. "cursor" should be
- * pointing to the colon that precedes the operating
- * system type.
- */
- if (*cursor != ':')
- *error_p = true;
- else
- {
- cursor++; /* Go over colon */
- /* Skip over operating system field. */
- while (*cursor != ':' && *cursor != 'r')
- cursor++;
- if (*cursor != ':')
- *error_p = true;
- else
- {
- int i; /* Index into *ident_username */
- cursor++; /* Go over colon */
- while (isblank(*cursor))
- cursor++; /* skip blanks */
- /* Rest of line is username. Copy it over. */
- i = 0;
- while (*cursor != 'r' && i < IDENT_USERNAME_MAX)
- ident_username[i++] = *cursor++;
- ident_username[i] = ' ';
- *error_p = false;
- }
- }
- }
- }
- }
- }
- static void
- ident(const struct in_addr remote_ip_addr, const struct in_addr local_ip_addr,
- const ushort remote_port, const ushort local_port,
- bool *ident_failed, char *ident_username)
- {
- /*--------------------------------------------------------------------------
- Talk to the ident server on host "remote_ip_addr" and find out who
- owns the tcp connection from his port "remote_port" to port
- "local_port_addr" on host "local_ip_addr". Return the username the
- ident server gives as "*ident_username".
- IP addresses and port numbers are in network byte order.
- But iff we're unable to get the information from ident, return
- *ident_failed == true (and *ident_username undefined).
- ----------------------------------------------------------------------------*/
- int sock_fd, /* File descriptor for socket on which we
- * talk to Ident */
- rc; /* Return code from a locally called
- * function */
- sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
- if (sock_fd == -1)
- {
- 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,%dn",
- 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] = ' ';
- interpret_ident_response(ident_response, &error, ident_username);
- *ident_failed = error;
- }
- }
- close(sock_fd);
- }
- }
- }
- static void
- parse_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] = ' ';
- file_pguser[0] = ' ';
- file_iuser[0] = ' ';
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- {
- strcpy(file_map, buf);
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- {
- strcpy(file_iuser, buf);
- next_token(file, buf, sizeof(buf));
- if (buf[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 void
- verify_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 void
- verify_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] == ' ')
- {
- *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);
- }
- }
- int
- authident(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 3
- struct CharsetItem
- {
- char Orig[MAX_TOKEN];
- char Dest[MAX_TOKEN];
- char Table[MAX_TOKEN];
- };
- int
- InRange(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++ = ' ';
- 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++ = ' ';
- 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;
- }
- void
- GetCharSetByHost(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 = ' ';
- 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] != ' ')
- {
- 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] != ' ')
- {
- if (InRange(buf, host))
- {
- /* Read the charset */
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- strcpy(HostCharset, buf);
- }
- }
- break;
- case KEY_BASE:
- /* Read the base charset */
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- strcpy(BaseCharset, buf);
- break;
- case KEY_TABLE:
- /* Read the original charset */
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- {
- strcpy(OrigCharset, buf);
- /* Read the destination charset */
- next_token(file, buf, sizeof(buf));
- if (buf[0] != ' ')
- {
- strcpy(DestCharset, buf);
- /* Read the table filename */
- next_token(file, buf, sizeof(buf));
- if (buf[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]);
- }
- }
- #endif
- int
- hba_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;
- }