⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hba.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
check_db(const char *dbname, const char *role, char *param_str){	char	   *tok;	for (tok = strtok(param_str, MULTI_VALUE_SEP);		 tok != NULL;		 tok = strtok(NULL, MULTI_VALUE_SEP))	{		if (strcmp(tok, "all\n") == 0)			return true;		else if (strcmp(tok, "sameuser\n") == 0)		{			if (strcmp(dbname, role) == 0)				return true;		}		else if (strcmp(tok, "samegroup\n") == 0 ||				 strcmp(tok, "samerole\n") == 0)		{			if (is_member(role, dbname))				return true;		}		else if (strcmp(tok, dbname) == 0)			return true;	}	return false;}/* *	Scan the rest of a host record (after the mask field) *	and return the interpretation of it as *userauth_p, *auth_arg_p, and *	*error_p.  *line_item points to the next token of the line, and is *	advanced over successfully-read tokens. */static voidparse_hba_auth(ListCell **line_item, UserAuth *userauth_p,			   char **auth_arg_p, bool *error_p){	char	   *token;	*auth_arg_p = NULL;	if (!*line_item)	{		*error_p = true;		return;	}	token = lfirst(*line_item);	if (strcmp(token, "trust") == 0)		*userauth_p = uaTrust;	else if (strcmp(token, "ident") == 0)		*userauth_p = uaIdent;	else if (strcmp(token, "password") == 0)		*userauth_p = uaPassword;	else if (strcmp(token, "krb5") == 0)		*userauth_p = uaKrb5;	else if (strcmp(token, "reject") == 0)		*userauth_p = uaReject;	else if (strcmp(token, "md5") == 0)		*userauth_p = uaMD5;	else if (strcmp(token, "crypt") == 0)		*userauth_p = uaCrypt;#ifdef USE_PAM	else if (strcmp(token, "pam") == 0)		*userauth_p = uaPAM;#endif	else	{		*error_p = true;		return;	}	*line_item = lnext(*line_item);	/* Get the authentication argument token, if any */	if (*line_item)	{		token = lfirst(*line_item);		*auth_arg_p = pstrdup(token);		*line_item = lnext(*line_item);		/* If there is more on the line, it is an error */		if (*line_item)			*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, int line_num, hbaPort *port,		  bool *found_p, bool *error_p){	char	   *token;	char	   *db;	char	   *role;	struct addrinfo *gai_result;	struct addrinfo hints;	int			ret;	struct sockaddr_storage addr;	struct sockaddr_storage mask;	char	   *cidr_slash;	ListCell   *line_item;	line_item = list_head(line);	/* Check the record type. */	token = lfirst(line_item);	if (strcmp(token, "local") == 0)	{		/* Get the database. */		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		db = lfirst(line_item);		/* Get the role. */		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		role = lfirst(line_item);		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		/* Read the rest of the line. */		parse_hba_auth(&line_item, &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 == 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_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		db = lfirst(line_item);		/* Get the role. */		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		role = lfirst(line_item);		/* Read the IP address field. (with or without CIDR netmask) */		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		token = lfirst(line_item);		/* 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 = pg_getaddrinfo_all(token, NULL, &hints, &gai_result);		if (ret || !gai_result)		{			ereport(LOG,					(errcode(ERRCODE_CONFIG_FILE_ERROR),			   errmsg("invalid IP address \"%s\" in file \"%s\" line %d: %s",					  token, HbaFileName, line_num,					  gai_strerror(ret))));			if (cidr_slash)				*cidr_slash = '/';			if (gai_result)				pg_freeaddrinfo_all(hints.ai_family, gai_result);			goto hba_other_error;		}		if (cidr_slash)			*cidr_slash = '/';		memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);		pg_freeaddrinfo_all(hints.ai_family, gai_result);		/* Get the netmask */		if (cidr_slash)		{			if (pg_sockaddr_cidr_mask(&mask, cidr_slash + 1,									  addr.ss_family) < 0)				goto hba_syntax;		}		else		{			/* Read the mask field. */			line_item = lnext(line_item);			if (!line_item)				goto hba_syntax;			token = lfirst(line_item);			ret = pg_getaddrinfo_all(token, NULL, &hints, &gai_result);			if (ret || !gai_result)			{				ereport(LOG,						(errcode(ERRCODE_CONFIG_FILE_ERROR),				  errmsg("invalid IP mask \"%s\" in file \"%s\" line %d: %s",						 token, HbaFileName, line_num,						 gai_strerror(ret))));				if (gai_result)					pg_freeaddrinfo_all(hints.ai_family, gai_result);				goto hba_other_error;			}			memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen);			pg_freeaddrinfo_all(hints.ai_family, gai_result);			if (addr.ss_family != mask.ss_family)			{				ereport(LOG,						(errcode(ERRCODE_CONFIG_FILE_ERROR),						 errmsg("IP address and mask do not match in file \"%s\" line %d",								HbaFileName, line_num)));				goto hba_other_error;			}		}		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)			{				pg_promote_v4_to_v6_addr(&addr);				pg_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 (!pg_range_sockaddr(&port->raddr.addr, &addr, &mask))			return;		/* Read the rest of the line. */		line_item = lnext(line_item);		if (!line_item)			goto hba_syntax;		parse_hba_auth(&line_item, &port->auth_method,					   &port->auth_arg, error_p);		if (*error_p)			goto hba_syntax;	}	else		goto hba_syntax;	/* Does the entry match database and role? */	if (!check_db(port->database_name, port->user_name, db))		return;	if (!check_role(port->user_name, role))		return;	/* Success */	*found_p = true;	return;hba_syntax:	if (line_item)		ereport(LOG,				(errcode(ERRCODE_CONFIG_FILE_ERROR),			  errmsg("invalid entry in file \"%s\" at line %d, token \"%s\"",					 HbaFileName, line_num,					 (char *) lfirst(line_item))));	else		ereport(LOG,				(errcode(ERRCODE_CONFIG_FILE_ERROR),				 errmsg("missing field in file \"%s\" at end of line %d",						HbaFileName, line_num)));	/* Come here if suitable message already logged */hba_other_error:	*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;	ListCell   *line;	ListCell   *line_num;	forboth(line, hba_lines, line_num, hba_line_nums)	{		parse_hba(lfirst(line), lfirst_int(line_num),				  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;}/* *	 Load role/password mapping file */voidload_role(void){	char	   *filename;	FILE	   *role_file;	/* Discard any old data */	if (role_lines || role_line_nums)		free_lines(&role_lines, &role_line_nums);	if (role_sorted)		pfree(role_sorted);	role_sorted = NULL;	role_length = 0;	/* Read in the file contents */	filename = auth_getflatfilename();	role_file = AllocateFile(filename, "r");	if (role_file == NULL)	{		/* no complaint if not there */		if (errno != ENOENT)			ereport(LOG,					(errcode_for_file_access(),					 errmsg("could not open file \"%s\": %m", filename)));		pfree(filename);		return;	}	tokenize_file(filename, role_file, &role_lines, &role_line_nums);	FreeFile(role_file);	pfree(filename);	/* create array for binary searching */	role_length = list_length(role_lines);	if (role_length)	{		int			i = 0;		ListCell   *line;		/* We assume the flat file was written already-sorted */		role_sorted = palloc(role_length * sizeof(List *));		foreach(line, role_lines)			role_sorted[i++] = lfirst(line);	}}/* * Read the config file and create a List of Lists of tokens in the file. */voidload_hba(void){	FILE	   *file;	if (hba_lines || hba_line_nums)		free_lines(&hba_lines, &hba_line_nums);	file = AllocateFile(HbaFileName, "r");	/* Failure is fatal since with no HBA entries we can do nothing... */	if (file == NULL)		ereport(FATAL,				(errcode_for_file_access(),				 errmsg("could not open configuration file \"%s\": %m",						HbaFileName)));	tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums);	FreeFile(file);}/* * Read and parse one line from the flat pg_database file. * * Returns TRUE on success, FALSE if EOF; bad data causes elog(FATAL). * * Output parameters: *	dbname: gets database name (must be of size NAMEDATALEN bytes) *	dboid: gets database OID *	dbtablespace: gets database's default tablespace's OID *	dbfrozenxid: gets database's frozen XID *	dbvacuumxid: gets database's vacuum XID * * This is not much related to the other functions in hba.c, but we put it * here because it uses the next_token() infrastructure. */boolread_pg_database_line(FILE *fp, char *dbname, Oid *dboid,					  Oid *dbtablespace, TransactionId *dbfrozenxid,					  TransactionId *dbvacuumxid){	char		buf[MAX_TOKEN];	if (feof(fp))		return false;	if (!next_token(fp, buf, sizeof(buf)))		return false;	if (strlen(buf) >= NAMEDATALEN)		elog(FATAL, "bad data in flat pg_database file");	strcpy(dbname, buf);	next_token(fp, buf, sizeof(buf));	if (!isdigit((unsigned char) buf[0]))		elog(FATAL, "bad data in flat pg_database file");	*dboid = atooid(buf);	next_token(fp, buf, sizeof(buf));	if (!isdigit((unsigned char) buf[0]))		elog(FATAL, "bad data in flat pg_database file");	*dbtablespace = atooid(buf);	next_token(fp, buf, sizeof(buf));	if (!isdigit((unsigned char) buf[0]))		elog(FATAL, "bad data in flat pg_database file");	*dbfrozenxid = atoxid(buf);	next_token(fp, buf, sizeof(buf));	if (!isdigit((unsigned char) buf[0]))		elog(FATAL, "bad data in flat pg_database file");	*dbvacuumxid = atoxid(buf);	/* expect EOL next */	if (next_token(fp, buf, sizeof(buf)))		elog(FATAL, "bad data in flat pg_database file");	return true;}/* *	Process one line from the ident config file. * *	Take the line and compare it to the needed map, pg_role and ident_user. *	*found_p and *error_p are set according to our results. */static voidparse_ident_usermap(List *line, int line_number, const char *usermap_name,					const char *pg_role, const char *ident_user,					bool *found_p, bool *error_p){	ListCell   *line_item;	char	   *token;	char	   *file_map;	char	   *file_pgrole;	char	   *file_ident_user;	*found_p = false;	*error_p = false;	Assert(line != NIL);	line_item = list_head(line);	/* Get the map token (must exist) */	token = lfirst(line_item);	file_map = token;	/* Get the ident user token */	line_item = lnext(line_item);	if (!line_item)		goto ident_syntax;	token = lfirst(line_item);	file_ident_user = token;	/* Get the PG rolename token */	line_item = lnext(line_item);	if (!line_item)		goto ident_syntax;	token = lfirst(line_item);	file_pgrole = token;	/* Match? */	if (strcmp(file_map, usermap_name) == 0 &&		strcmp(file_pgrole, pg_role) == 0 &&		strcmp(file_ident_user, ident_user) == 0)		*found_p = true;	return;ident_syntax:	ereport(LOG,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -