Пример #1
0
static int
pg_krb5_init(PQExpBuffer errorMessage, struct krb5_info * info)
{
	krb5_error_code retval;

	if (info->pg_krb5_initialised)
		return STATUS_OK;

	retval = krb5_init_context(&(info->pg_krb5_context));
	if (retval)
	{
		printfPQExpBuffer(errorMessage,
						  "pg_krb5_init: krb5_init_context: %s\n",
						  error_message(retval));
		return STATUS_ERROR;
	}

	retval = krb5_cc_default(info->pg_krb5_context, &(info->pg_krb5_ccache));
	if (retval)
	{
		printfPQExpBuffer(errorMessage,
						  "pg_krb5_init: krb5_cc_default: %s\n",
						  error_message(retval));
		krb5_free_context(info->pg_krb5_context);
		return STATUS_ERROR;
	}

	retval = krb5_cc_get_principal(info->pg_krb5_context, info->pg_krb5_ccache,
								   &(info->pg_krb5_client));
	if (retval)
	{
		printfPQExpBuffer(errorMessage,
						  "pg_krb5_init: krb5_cc_get_principal: %s\n",
						  error_message(retval));
		krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
		krb5_free_context(info->pg_krb5_context);
		return STATUS_ERROR;
	}

	retval = krb5_unparse_name(info->pg_krb5_context, info->pg_krb5_client, &(info->pg_krb5_name));
	if (retval)
	{
		printfPQExpBuffer(errorMessage,
						  "pg_krb5_init: krb5_unparse_name: %s\n",
						  error_message(retval));
		krb5_free_principal(info->pg_krb5_context, info->pg_krb5_client);
		krb5_cc_close(info->pg_krb5_context, info->pg_krb5_ccache);
		krb5_free_context(info->pg_krb5_context);
		return STATUS_ERROR;
	}

	info->pg_krb5_name = pg_an_to_ln(info->pg_krb5_name);

	info->pg_krb5_initialised = 1;
	return STATUS_OK;
}
Пример #2
0
static int
pg_krb5_init(char *PQerrormsg)
{
	krb5_error_code retval;

	if (pg_krb5_initialised)
		return STATUS_OK;

	retval = krb5_init_context(&pg_krb5_context);
	if (retval)
	{
		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
				 "pg_krb5_init: krb5_init_context: %s\n",
				 error_message(retval));
		return STATUS_ERROR;
	}

	retval = krb5_cc_default(pg_krb5_context, &pg_krb5_ccache);
	if (retval)
	{
		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
				 "pg_krb5_init: krb5_cc_default: %s\n",
				 error_message(retval));
		krb5_free_context(pg_krb5_context);
		return STATUS_ERROR;
	}

	retval = krb5_cc_get_principal(pg_krb5_context, pg_krb5_ccache,
								   &pg_krb5_client);
	if (retval)
	{
		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
				 "pg_krb5_init: krb5_cc_get_principal: %s\n",
				 error_message(retval));
		krb5_cc_close(pg_krb5_context, pg_krb5_ccache);
		krb5_free_context(pg_krb5_context);
		return STATUS_ERROR;
	}

	retval = krb5_unparse_name(pg_krb5_context, pg_krb5_client, &pg_krb5_name);
	if (retval)
	{
		snprintf(PQerrormsg, PQERRORMSG_LENGTH,
				 "pg_krb5_init: krb5_unparse_name: %s\n",
				 error_message(retval));
		krb5_free_principal(pg_krb5_context, pg_krb5_client);
		krb5_cc_close(pg_krb5_context, pg_krb5_ccache);
		krb5_free_context(pg_krb5_context);
		return STATUS_ERROR;
	}

	pg_krb5_name = pg_an_to_ln(pg_krb5_name);

	pg_krb5_initialised = 1;
	return STATUS_OK;
}
Пример #3
0
/*
 * pg_krb5_recvauth -- server routine to receive authentication information
 *					   from the client
 *
 * We still need to compare the username obtained from the client's setup
 * packet to the authenticated name, as described in pg_krb4_recvauth.	This
 * is a bit more problematic in v5, as described above in pg_an_to_ln.
 *
 * We have our own keytab file because postgres is unlikely to run as root,
 * and so cannot read the default keytab.
 */
static int
pg_krb5_recvauth(Port *port)
{
	krb5_error_code retval;
	int			ret;
	krb5_auth_context auth_context = NULL;
	krb5_ticket *ticket;
	char	   *kusername;

	ret = pg_krb5_init();
	if (ret != STATUS_OK)
		return ret;

	retval = krb5_recvauth(pg_krb5_context, &auth_context,
						   (krb5_pointer) & port->sock, PG_KRB_SRVNAM,
						   pg_krb5_server, 0, pg_krb5_keytab, &ticket);
	if (retval)
	{
		ereport(LOG,
				(errmsg("Kerberos recvauth returned error %d",
						retval)));
		com_err("postgres", retval, "from krb5_recvauth");
		return STATUS_ERROR;
	}

	/*
	 * The "client" structure comes out of the ticket and is therefore
	 * authenticated.  Use it to check the username obtained from the
	 * postmaster startup packet.
	 *
	 * I have no idea why this is considered necessary.
	 */
#if defined(HAVE_KRB5_TICKET_ENC_PART2)
	retval = krb5_unparse_name(pg_krb5_context,
							   ticket->enc_part2->client, &kusername);
#elif defined(HAVE_KRB5_TICKET_CLIENT)
	retval = krb5_unparse_name(pg_krb5_context,
							   ticket->client, &kusername);
#else
#error "bogus configuration"
#endif
	if (retval)
	{
		ereport(LOG,
				(errmsg("Kerberos unparse_name returned error %d",
						retval)));
		com_err("postgres", retval, "while unparsing client name");
		krb5_free_ticket(pg_krb5_context, ticket);
		krb5_auth_con_free(pg_krb5_context, auth_context);
		return STATUS_ERROR;
	}

	kusername = pg_an_to_ln(kusername);
	if (strncmp(port->user_name, kusername, SM_DATABASE_USER))
	{
		ereport(LOG,
				(errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")",
						port->user_name, kusername)));
		ret = STATUS_ERROR;
	}
	else
		ret = STATUS_OK;

	krb5_free_ticket(pg_krb5_context, ticket);
	krb5_auth_con_free(pg_krb5_context, auth_context);
	free(kusername);

	return ret;
}