Пример #1
0
/* --------------------------------
 * init_query_cache_info() - allocate memory for query_cache_info and stores query
 *
 * returns 0 on success, -1 otherwise
`* --------------------------------
 */
static int
init_query_cache_info(POOL_CONNECTION *pc, char *database, char *query)
{
	int query_len;				/* length of the SELECT query to be cached */

	query_cache_info = (QueryCacheInfo *)malloc(sizeof(QueryCacheInfo));
	if (malloc_failed(query_cache_info))
		return -1;

	/* query */
	query_len = strlen(query);
	query_cache_info->query = (char *)malloc(query_len + 1);
	if (malloc_failed(query_cache_info->query))
		return -1;
	memcpy(query_cache_info->query, query, query_len + 1);

	/* md5_query */
	query_cache_info->md5_query = (char *)malloc(33); /* md5sum is always 33 bytes (including the '\0') */
	if (malloc_failed(query_cache_info->md5_query))
		return -1;
	pool_md5_hash(query_cache_info->query, query_len, query_cache_info->md5_query);

	/* malloc DEFAULT_CACHE_SIZE for query_cache_info->cache */
	query_cache_info->cache = (char *)malloc(DEFAULT_CACHE_SIZE);
	if (malloc_failed(query_cache_info->cache))
		return -1;
	query_cache_info->cache_size = DEFAULT_CACHE_SIZE;
	query_cache_info->cache_offset = 0;

	/* save database name */
	query_cache_info->db_name = (char *)malloc(strlen(database)+1);
	if (malloc_failed(query_cache_info->db_name))
		return -1;
	strcpy(query_cache_info->db_name, database);

	/* initialize create_timestamp */
	query_cache_info->create_time = NULL;

	return 0;
}
Пример #2
0
/*
 * Computes MD5 checksum of "passwd" (a null-terminated string) followed
 * by "salt" (which need not be null-terminated).
 *
 * Output format is a 32-hex-digit MD5 checksum.
 * Hence, the output buffer "buf" must be at least 33 bytes long.
 *
 * Returns 1 if okay, 0 on error (out of memory).
 */
int
pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
			   char *buf)
{
	size_t passwd_len = strlen(passwd);
	char *crypt_buf = malloc(passwd_len + salt_len);
	int ret;

	if (!crypt_buf)
		return 0;				/* failed */

	/*
	 * Place salt at the end because it may be known by users trying to crack
	 * the MD5 output.
	 */
	strcpy(crypt_buf, passwd);
	memcpy(crypt_buf + passwd_len, salt, salt_len);

	ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf);

	free(crypt_buf);

	return ret;
}
Пример #3
0
/* --------------------------------
 * pcp_authorize - authenticate with pgpool using username and password
 *
 * return 0 on success, -1 otherwise
 * --------------------------------
 */
static int
pcp_authorize(char *username, char *password)
{
	char tos;
	char *buf = NULL;
	int wsize;
	int rsize;
	char salt[4];
	char encrypt_buf[(MD5_PASSWD_LEN+1)*2];
	char md5[MD5_PASSWD_LEN+1];

	/* request salt */
	pcp_write(pc, "M", 1);
	wsize = htonl(sizeof(int));
	pcp_write(pc, &wsize, sizeof(int));
	if (pcp_flush(pc) < 0)
	{
		if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n");
		return -1;
	}

	if (pcp_read(pc, &tos, 1))
		return -1;
	if (pcp_read(pc, &rsize, sizeof(int)))
		return -1;
	rsize = ntohl(rsize);
	buf = (char *)malloc(rsize);
	if (buf == NULL)
	{
		errorcode = NOMEMERR;
		return -1;
	}
	if (pcp_read(pc, buf, rsize - sizeof(int)))
		return -1;
	memcpy(salt, buf, 4);
	free(buf);

	/* encrypt password */
	pool_md5_hash(password, strlen(password), md5);
	md5[MD5_PASSWD_LEN] = '\0';

	pool_md5_encrypt(md5, username, strlen(username),
					 encrypt_buf + MD5_PASSWD_LEN + 1);
	encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0';

	pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, 4,
					 encrypt_buf);
	encrypt_buf[MD5_PASSWD_LEN] = '\0';

	pcp_write(pc, "R", 1);
	wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int));
	pcp_write(pc, &wsize, sizeof(int));
	pcp_write(pc, username, strlen(username)+1);
	pcp_write(pc, encrypt_buf, strlen(encrypt_buf)+1);
	if (pcp_flush(pc) < 0)
	{
		if  (debug) fprintf(stderr, "DEBUG: could not send data to backend\n");
		return -1;
	}
	if (debug) fprintf(stderr, "DEBUG: send: tos=\"R\", len=%d\n", ntohl(wsize));

	if (pcp_read(pc, &tos, 1))
		return -1;
	if (pcp_read(pc, &rsize, sizeof(int)))
		return -1;
	rsize = ntohl(rsize);
	buf = (char *)malloc(rsize);
	if (buf == NULL)
	{
		errorcode = NOMEMERR;
		return -1;
	}
	if (pcp_read(pc, buf, rsize - sizeof(int)))
		return -1;
	if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf);

	if (tos == 'e')
	{
		if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf);
		errorcode = BACKENDERR;
	}
	else if (tos == 'r')
	{
		if (strcmp(buf, "AuthenticationOK") == 0)
		{
			free(buf);
			return 0;
		}

		if (debug) fprintf(stderr, "DEBUG: authentication failed. reason=%s\n", buf);
		errorcode = AUTHERR;
	}
	free(buf);

	return -1;
}
Пример #4
0
/* --------------------------------
 * pcp_authorize - authenticate with pgpool using username and password
 *
 * return 0 on success, -1 otherwise
 * --------------------------------
 */
static int
pcp_authorize(PCPConnInfo* pcpConn, char *username, char *password)
{
	int wsize;
	char salt[4];
	char* salt_ptr;
	char encrypt_buf[(MD5_PASSWD_LEN+1)*2];
	char md5[MD5_PASSWD_LEN+1];
	PCPResultInfo* pcpRes;

	if (password == NULL)
		password = "";

	if (username == NULL)
		username = "";

	if (PCPConnectionStatus(pcpConn) != PCP_CONNECTION_CONNECTED)
	{
		pcp_internal_error(pcpConn,
						   "ERROR: PCP authorization failed. invalid connection state.");
		return -1;
	}

	if (strlen(username) >= MAX_USER_PASSWD_LEN)
	{
		pcp_internal_error(pcpConn,
						   "ERROR: PCP authorization failed. username too long.");
		return -1;
	}

	/* request salt */
	pcp_write(pcpConn->pcpConn, "M", 1);
	wsize = htonl(sizeof(int));
	pcp_write(pcpConn->pcpConn, &wsize, sizeof(int));
	if (PCPFlush(pcpConn) < 0)
		return -1;

	pcpRes = process_pcp_response(pcpConn, 'M');
	if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK)
		return -1;

	salt_ptr = pcp_get_binary_data(pcpRes, 0);
	if(salt_ptr == NULL)
		return -1;
	memcpy(salt, salt_ptr, 4);

	/* encrypt password */
	pool_md5_hash(password, strlen(password), md5);
	md5[MD5_PASSWD_LEN] = '\0';

	pool_md5_encrypt(md5, username, strlen(username),
					 encrypt_buf + MD5_PASSWD_LEN + 1);
	encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0';

	pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, 4,
					 encrypt_buf);
	encrypt_buf[MD5_PASSWD_LEN] = '\0';

	pcp_write(pcpConn->pcpConn, "R", 1);
	wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int));
	pcp_write(pcpConn->pcpConn, &wsize, sizeof(int));
	pcp_write(pcpConn->pcpConn, username, strlen(username)+1);
	pcp_write(pcpConn->pcpConn, encrypt_buf, strlen(encrypt_buf)+1);
	if (PCPFlush(pcpConn) < 0)
		return -1;
	pcpRes = process_pcp_response(pcpConn, 'R');
	if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK)
		return -1;
	pcp_free_result(pcpConn);
	return 0;
}
Пример #5
0
/* --------------------------------
 * pool_query_cache_lookup - retrieve query cache from the SystemDB
 *
 * creates a SQL query string for searching a cache from the SystemDB.
 *
 * returns POOL_CONTINUE if cache is found. returns POOL_END if cache was
 * not found. returns POOL_ERROR if an error has been encountered while
 * searching.
 *
 * Note that POOL_END and POOL_ERROR are treated the same by the caller
 * (pool_process_query.c).
 * POOL_END and POOL_ERROR both indicates to the caller that the search
 * query must be forwarded to the backends in order to retrieve data and
 * the result be cached.
 * Only difference is that POOL_ERROR indicates that some fatal error has
 * occured; query cache function, however, should be seemless to the user
 * whether cache was not found or error has occured during cache retrieve.
 * --------------------------------
 */
POOL_STATUS
pool_query_cache_lookup(POOL_CONNECTION *frontend, char *query, char *database, char tstate)
{
	char *sql = NULL;
	int sql_len;
	char md5_query[33];
	struct timeval timeout;
	int status;

	if (! system_db_connection_exists())
		return POOL_ERROR;		/* same as POOL_END ... at least for now */

	sql_len =
		strlen(pool_config->system_db_schema) +
		strlen(QUERY_CACHE_TABLE_NAME) +
		sizeof(md5_query) +
		strlen(database) +
		64;
	sql = (char *)malloc(sql_len);
	if (malloc_failed(sql))
		return POOL_ERROR;		/* should I exit here rather than returning an error? */

	/* cached data lookup */
	pool_md5_hash(query, strlen(query), md5_query);
	snprintf(sql, sql_len, "SELECT value FROM %s.%s WHERE hash = '%s' AND dbname = '%s'",
			 pool_config->system_db_schema,
			 QUERY_CACHE_TABLE_NAME,
			 md5_query,
			 database);

	/* set timeout value for select */
	timeout.tv_sec = pool_config->child_life_time;
	timeout.tv_usec = 0;

	pool_debug("pool_query_cache_lookup: searching cache for query: \"%s\"", query);
	status = search_system_db_for_cache(frontend, sql, strlen(sql)+1, &timeout, tstate);

	/* make sure that the remaining data is discarded */
	SYSDB_CON->po = 0;
	SYSDB_CON->len = 0;

	free(sql);

	/* cache found, and no backend communication needed */
	if (status == CACHE_FOUND)
	{
		return POOL_CONTINUE;
	}

	/* cache not found */

	if (status == CACHE_ERROR)
	{
		pool_error("pool_query_cache_lookup: query cache lookup failed");
		/* reset the SystemDB connection */
		if (system_db_info->pgconn)
			pool_close_libpq_connection();
		return POOL_ERROR;		/* same as POOL_END ... at least for now */
	}

	pool_debug("pool_query_cache_lookup: query cache not found");
	return POOL_END;
}
Пример #6
0
int
main(int argc, char *argv[])
{
#define PRINT_USAGE(exit_code)	print_usage(argv[0], exit_code)

	char conf_file[POOLMAXPATHLEN+1];
	char username[MAX_INPUT_SIZE+1];
	int opt;
	int optindex;
	bool md5auth = false;
	bool prompt = false;

	static struct option long_options[] = {
		{"help", no_argument, NULL, 'h'},
		{"prompt", no_argument, NULL, 'p'},
		{"md5auth", no_argument, NULL, 'm'},
		{"username", required_argument, NULL, 'u'},
		{"config-file", required_argument, NULL, 'f'},
		{NULL, 0, NULL, 0}
	};

	snprintf(conf_file, sizeof(conf_file), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);

	/* initialize username buffer with zeros so that we can use strlen on it later
	   to check if a username was given on the command line
	 */
	memset(username, 0, MAX_INPUT_SIZE+1);

    while ((opt = getopt_long(argc, argv, "hpmf:u:", long_options, &optindex)) != -1)
	{
		switch (opt)
		{
			case 'p':    /* prompt for password */
				prompt = true;
				break;

			case 'm':	/* produce md5 authentication password */
				md5auth = true;
				break;

			case 'f':	/* specify configuration file */
				if (!optarg)
				{
					PRINT_USAGE(EXIT_SUCCESS);
				}
				strlcpy(conf_file, optarg, sizeof(conf_file));
				break;

			case 'u':
				if (!optarg)
				{
					PRINT_USAGE(EXIT_SUCCESS);
				}
				/* check the input limit early */
				if (strlen(optarg) > MAX_INPUT_SIZE)
				{
					fprintf(stderr, "Error: input exceeds maximum username length!\n\n");
					exit(EXIT_FAILURE);
				}
				strlcpy(username, optarg, sizeof(username));
				break;

			default:
				PRINT_USAGE(EXIT_SUCCESS);
				break;
		}
	}				

	/* Prompt for password. */
	if (prompt)
	{
		char	 md5[MD5_PASSWD_LEN+1];
		char	 buf[MAX_INPUT_SIZE+1];
		int		 len;

		set_tio_attr(1);
		printf("password: "******"Couldn't read input from stdin. (fgets(): %s)",
					strerror(eno));

			exit(EXIT_FAILURE);
		}
		printf("\n");
		set_tio_attr(0);

		/* Remove LF at the end of line, if there is any. */
		len = strlen(buf);
		if (len > 0 && buf[len-1] == '\n')
		{
			buf[len-1] = '\0';
			len--;
		}

		if (md5auth)
		{
			update_pool_passwd(conf_file, username, buf);
		}
		else
		{
			pool_md5_hash(buf, len, md5);
			printf("%s\n", md5);
		}
	}

	/* Read password from argv. */
	else
	{
		char	md5[POOL_PASSWD_LEN+1];
		int		len;

		if (optind >= argc)
		{
			PRINT_USAGE(EXIT_FAILURE);
		}
			
		len = strlen(argv[optind]);

		if (len > MAX_INPUT_SIZE)
		{
			fprintf(stderr, "Error: Input exceeds maximum password length!\n\n");
			PRINT_USAGE(EXIT_FAILURE);
		}

		if (md5auth)
		{
			update_pool_passwd(conf_file, username, argv[optind]);
		}
		else
		{
			pool_md5_hash(argv[optind], len, md5);
			printf("%s\n", md5);
		}
	}

	return EXIT_SUCCESS;
}
Пример #7
0
int
main(int argc, char *argv[])
{

#define PRINT_USAGE(exit_code)	print_usage(argv[0], exit_code)
#define COMPARE_ARG(arg)		(!strcmp(argv[1], arg))

	if (argc != 2)
		PRINT_USAGE(EXIT_FAILURE);
	else if (COMPARE_ARG("--help") || COMPARE_ARG("-h"))
		PRINT_USAGE(EXIT_SUCCESS);

	/* Prompt for password. */
	else if (COMPARE_ARG("--prompt") || COMPARE_ARG("-p"))
	{
	   	char	 md5[MD5_PASSWD_LEN+1];
		char	 buf[MAX_INPUT_SIZE+1];
		int		 len;

		set_tio_attr(1);
		printf("password: "******"Couldn't read input from stdin. (fgets(): %s)",
					strerror(eno));

			exit(EXIT_FAILURE);
		}
		set_tio_attr(0);

		/* Remove LF at the end of line, if there is any. */
		len = strlen(buf);
		if (len > 0 && buf[len-1] == '\n')
		{
			buf[len-1] = '\0';
			len--;
		}

		pool_md5_hash(buf, len, md5);
		printf("\n%s\n", md5);
	}

	/* Read password from argv[1]. */
	else
	{
		char	md5[MD5_PASSWD_LEN+1];
		int		len = strlen(argv[1]);

		if (len > MAX_INPUT_SIZE)
		{
			fprintf(stderr, "Error: Input exceeds maximum password length!\n\n");
			PRINT_USAGE(EXIT_FAILURE);
		}

		pool_md5_hash(argv[1], len, md5);
		printf("%s\n", md5);
	}

	return EXIT_SUCCESS;
}