Esempio n. 1
0
/*
 * do frontend <-> pgpool authentication based on pool_hba.conf
 */
void ClientAuthentication(POOL_CONNECTION *frontend)
{
	POOL_STATUS status = POOL_ERROR;

	if (! hba_getauthmethod(frontend))
	{
		pool_error("missing or erroneous pool_hba.conf file");
		pool_send_error_message(frontend, frontend->protoVersion, "XX000",
								"missing or erroneous pool_hba.conf file", "",
								"See pgpool log for details.", __FILE__, __LINE__);
		close_all_backend_connections();
		/*
		 * use exit(2) since this is not so fatal. other entries in
		 * pool_hba.conf may be valid, so treat it as reject.
		 */
		child_exit(2);
	}

	switch (frontend->auth_method)
	{
		case uaReject:
		{
            /*
			 * This could have come from an explicit "reject" entry in
			 * pool_hba.conf, but more likely it means there was no matching
			 * entry.  Take pity on the poor user and issue a helpful
			 * error message.  NOTE: this is not a security breach,
			 * because all the info reported here is known at the frontend
			 * and must be assumed known to bad guys. We're merely helping
			 * out the less clueful good guys.
			 */
			char hostinfo[NI_MAXHOST];
			char *errmessage;
			int messagelen;

			getnameinfo_all(&frontend->raddr.addr, frontend->raddr.salen,
							hostinfo, sizeof(hostinfo),
							NULL, 0,
							NI_NUMERICHOST);

			messagelen = sizeof(hostinfo) +
				strlen(frontend->username) + strlen(frontend->database) + 80;
			if ((errmessage = (char *)malloc(messagelen+1)) == NULL)
			{
				pool_error("ClientAuthentication: malloc failed: %s", strerror(errno));
				child_exit(1);
			}

#ifdef USE_SSL
			snprintf(errmessage, messagelen+7, /* +7 is for "SSL off" */
					 "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
					 hostinfo, frontend->username, frontend->database,
					 frontend->ssl ? "SSL on" : "SSL off");
#else
			snprintf(errmessage, messagelen,
					 "no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
					 hostinfo, frontend->username, frontend->database);
#endif
			pool_error(errmessage);
			pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage,
									"", "", __FILE__, __LINE__);

			free(errmessage);
			break;
		}

/* 		case uaKrb4: */
/* 			break; */

/* 		case uaKrb5: */
/* 			break; */

/* 		case uaIdent: */
/* 			break; */

/* 		case uaMD5: */
/* 			break; */

/* 		case uaCrypt: */
/* 			break; */

/* 		case uaPassword: */
/* 			break; */

#ifdef USE_PAM
		case uaPAM:
			pam_frontend_kludge = frontend;
			status = CheckPAMAuth(frontend, frontend->username, "");
			break;
#endif /* USE_PAM */

		case uaTrust:
			status = POOL_CONTINUE;
			break;
	}

 	if (status == POOL_CONTINUE)
 		sendAuthRequest(frontend, AUTH_REQ_OK);
 	else if (status != POOL_CONTINUE)
		auth_failed(frontend);
}
Esempio n. 2
0
/*
 * Client authentication starts here.  If there is an error, this
 * function does not return and the backend process is terminated.
 */
void
ClientAuthentication(Port *port)
{
	int			status = STATUS_ERROR;

	/*
	 * Get the authentication method to use for this frontend/database
	 * combination.  Note: a failure return indicates a problem with the
	 * hba config file, not with the request.  hba.c should have dropped
	 * an error message into the postmaster logfile if it failed.
	 */
	if (hba_getauthmethod(port) != STATUS_OK)
		ereport(FATAL,
				(errcode(ERRCODE_CONFIG_FILE_ERROR),
				 errmsg("missing or erroneous pg_hba.conf file"),
				 errhint("See server log for details.")));

	switch (port->auth_method)
	{
		case uaReject:

			/*
			 * This could have come from an explicit "reject" entry in
			 * pg_hba.conf, but more likely it means there was no matching
			 * entry.  Take pity on the poor user and issue a helpful
			 * error message.  NOTE: this is not a security breach,
			 * because all the info reported here is known at the frontend
			 * and must be assumed known to bad guys. We're merely helping
			 * out the less clueful good guys.
			 */
			{
				char		hostinfo[NI_MAXHOST];

				getnameinfo_all(&port->raddr.addr, port->raddr.salen,
								hostinfo, sizeof(hostinfo),
								NULL, 0,
								NI_NUMERICHOST);

#ifdef USE_SSL
				ereport(FATAL,
				   (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
					errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
						   hostinfo, port->user_name, port->database_name,
				   port->ssl ? gettext("SSL on") : gettext("SSL off"))));
#else
				ereport(FATAL,
				   (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
					errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
					   hostinfo, port->user_name, port->database_name)));
#endif
				break;
			}

		case uaKrb4:
			/* Kerberos 4 only seems to work with AF_INET. */
			if (port->raddr.addr.ss_family != AF_INET
				|| port->laddr.addr.ss_family != AF_INET)
				ereport(FATAL,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				   errmsg("Kerberos 4 only supports IPv4 connections")));
			sendAuthRequest(port, AUTH_REQ_KRB4);
			status = pg_krb4_recvauth(port);
			break;

		case uaKrb5:
			sendAuthRequest(port, AUTH_REQ_KRB5);
			status = pg_krb5_recvauth(port);
			break;

		case uaIdent:
			/*
			 * If we are doing ident on unix-domain sockets, use SCM_CREDS
			 * only if it is defined and SO_PEERCRED isn't.
			 */
#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
	(defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || \
	 (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS)))
			if (port->raddr.addr.ss_family == AF_UNIX)
			{
#if defined(HAVE_STRUCT_FCRED) || defined(HAVE_STRUCT_SOCKCRED)
				/*
				 * Receive credentials on next message receipt, BSD/OS,
				 * NetBSD. We need to set this before the client sends the
				 * next packet.
				 */
				int			on = 1;

				if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0)
					ereport(FATAL,
							(errcode_for_socket_access(),
					 errmsg("could not enable credential reception: %m")));
#endif

				sendAuthRequest(port, AUTH_REQ_SCM_CREDS);
			}
#endif
			status = authident(port);
			break;

		case uaMD5:
			sendAuthRequest(port, AUTH_REQ_MD5);
			status = recv_and_check_password_packet(port);
			break;

		case uaCrypt:
			sendAuthRequest(port, AUTH_REQ_CRYPT);
			status = recv_and_check_password_packet(port);
			break;

		case uaPassword:
			sendAuthRequest(port, AUTH_REQ_PASSWORD);
			status = recv_and_check_password_packet(port);
			break;

#ifdef USE_PAM
		case uaPAM:
			pam_port_cludge = port;
			status = CheckPAMAuth(port, port->user_name, "");
			break;
#endif   /* USE_PAM */

		case uaTrust:
			status = STATUS_OK;
			break;
	}

	if (status == STATUS_OK)
		sendAuthRequest(port, AUTH_REQ_OK);
	else
		auth_failed(port, status);
}