<commit_before>/*-------------------------------------------------------------------------
 *
 * 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).
 *
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.90 2002/12/06 04:37:02 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/socket.h>
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
#include <sys/uio.h>
#include <sys/ucred.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#include "commands/user.h"
#include "libpq/crypt.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "nodes/pg_list.h"
#include "storage/fd.h"


#define IDENT_USERNAME_MAX 512
/* Max size of username ident server can return */

/* This is used to separate values in multi-valued column strings */
#define MULTI_VALUE_SEP "\001"

/*
 * These variables hold the pre-parsed contents of the hba and ident
 * configuration files.  Each is a list of sublists, one sublist for
 * each (non-empty, non-comment) line of the file.	Each sublist's
 * first item is an integer line number (so we can give somewhat-useful
 * location info in error messages).  Remaining items are palloc'd strings,
 * one string per token on the line.  Note there will always be at least
 * one token, since blank lines are not entered in the data structure.
 */
static List *hba_lines = NIL;	/* pre-parsed contents of hba file */
static List *ident_lines = NIL; /* pre-parsed contents of ident file */
static List *group_lines = NIL; /* pre-parsed contents of group file */
static List *user_lines = NIL;	/* pre-parsed contents of user password
								 * file */

/* sorted entries so we can do binary search lookups */
static List **user_sorted = NULL;		/* sorted user list, for bsearch() */
static List **group_sorted = NULL;		/* sorted group list, for
										 * bsearch() */
static int	user_length;
static int	group_length;

static List *tokenize_file(FILE *file);
static char *tokenize_inc_file(const char *inc_filename);

/*
 * 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 == '\t' || c == '\r';
}


/*
 *	 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. Allow spaces in quoted
 *	 strings. Terminate on unquoted commas. Handle comments.
 */
void
next_token(FILE *fp, char *buf, const int bufsz)
{
	int			c;
	char	   *end_buf = buf + (bufsz - 1);
	bool		in_quote = false;
	bool		was_quote = false;

	/* Move over initial whitespace and commas */
	while ((c = getc(fp)) != EOF && (isblank(c) || c == ','))
		;

	if (c != EOF && c != '\n')
	{
		/*
		 * Build a token in buf of next characters up to EOF, EOL,
		 * unquoted comma, or unquoted whitespace.
		 */
		while (c != EOF && c != '\n' &&
			   (!isblank(c) || in_quote == true))
		{
			/* skip comments to EOL */
			if (c == '#' && !in_quote)
			{
				while ((c = getc(fp)) != EOF && c != '\n')
					;
				continue;
			}

			if (buf >= end_buf)
			{
				elog(LOG, "Token too long in authentication file, skipping, %s", buf);
				/* Discard remainder of line */
				while ((c = getc(fp)) != EOF && c != '\n')
					;
				buf[0] = '\0';
				break;
			}

			if (c != '"' || (c == '"' && was_quote))
				*buf++ = c;

			/* We pass back the comma so the caller knows there is more */
			if ((isblank(c) || c == ',') && !in_quote)
				break;

			/* Literal double-quote is two double-quotes */
			if (in_quote && c == '"')
				was_quote = !was_quote;<commit_msg>Fix line count error reporting in config files, like pg_hba.conf, per report from <NAME>.<commit_after>/*-------------------------------------------------------------------------
 *
 * 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).
 *
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.91 2002/12/11 22:17:11 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/socket.h>
#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
#include <sys/uio.h>
#include <sys/ucred.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#include "commands/user.h"
#include "libpq/crypt.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "nodes/pg_list.h"
#include "storage/fd.h"


#define IDENT_USERNAME_MAX 512
/* Max size of username ident server can return */

/* This is used to separate values in multi-valued column strings */
#define MULTI_VALUE_SEP "\001"

/*
 * These variables hold the pre-parsed contents of the hba and ident
 * configuration files.  Each is a list of sublists, one sublist for
 * each (non-empty, non-comment) line of the file.	Each sublist's
 * first item is an integer line number (so we can give somewhat-useful
 * location info in error messages).  Remaining items are palloc'd strings,
 * one string per token on the line.  Note there will always be at least
 * one token, since blank lines are not entered in the data structure.
 */
static List *hba_lines = NIL;	/* pre-parsed contents of hba file */
static List *ident_lines = NIL; /* pre-parsed contents of ident file */
static List *group_lines = NIL; /* pre-parsed contents of group file */
static List *user_lines = NIL;	/* pre-parsed contents of user password
								 * file */

/* sorted entries so we can do binary search lookups */
static List **user_sorted = NULL;		/* sorted user list, for bsearch() */
static List **group_sorted = NULL;		/* sorted group list, for
										 * bsearch() */
static int	user_length;
static int	group_length;

static List *tokenize_file(FILE *file);
static char *tokenize_inc_file(const char *inc_filename);

/*
 * 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 == '\t' || c == '\r';
}


/*
 *	 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. Allow spaces in quoted
 *	 strings. Terminate on unquoted commas. Handle comments.
 */
void
next_token(FILE *fp, char *buf, const int bufsz)
{
	int			c;
	char	   *start_buf = buf;
	char	   *end_buf = buf + (bufsz - 1);
	bool		in_quote = false;
	bool		was_quote = false;

	/* Move over initial whitespace and commas */
	while ((c = getc(fp)) != EOF && (isblank(c) || c == ','))
		;

	if (c != EOF && c != '\n')
	{
		/*
		 * Build a token in buf of next characters up to EOF, EOL,
		 * unquoted comma, or unquoted whitespace.
		 */
		while (c != EOF && c != '\n' &&
			   (!isblank(c) || in_quote == true))
		{
			/* skip comments to EOL */
			if (c == '#' && !in_quote)
			{
				while ((c = getc(fp)) != EOF && c != '\n')
					;
				/* If only comment, consume EOL too; return EOL */
				if (c != EOF && buf == start_buf)
					c = getc(fp);
				break;
			}

			if (buf >= end_buf)
			{
				elog(LOG, "Token too long in authentication file, skipping, %s", buf);
				/* Discard remainder of line */
				while ((c = getc(fp)) != EOF && c != '\n')
					;
				buf[0] = '\0';
				break;
			}

			if (c != '"' || (c == '"' && was_quote))
				*buf++ = c;

			/* We pass back the comma so the caller knows there is more */
			if ((isblank(c) || c == ',') && !in_quote)
				break;

			/* Literal double-quote is two double-quotes */
			if (in_quote && c == '"')
				was_quote = !was_quote;
{'fraction_non_alphanumeric': 0.15811020137198495, 'fraction_numerical': 0.008408940030980305, 'mean_word_length': 2.807497893850042, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '321087', 'n_tokens_mistral': 3218, 'n_tokens_neox': 2925, 'n_words': 1084}