Commit message: Fix gssrpc data leakage [CVE-2014-9423]

[MITKRB5-SA-2015-001] In svcauth_gss_accept_sec_context(), do not copy
bytes from the union context into the handle field we send to the
client.  We do not use this handle field, so just supply a fixed
string of "xxxx".

In gss_union_ctx_id_struct, remove the unused "interposer" field which
was causing part of the union context to remain uninitialized.

ticket: 8058 (new)
target_version: 1.13.1
tags: pullup
CVE: CVE-2014-9423
CWE: CWE-200
Vulnerability description: The svcauth_gss_accept_sec_context function in lib/rpc/svc_auth_gss.c in MIT Kerberos 5 (aka krb5) 1.11.x through 1.11.5, 1.12.x through 1.12.2, and 1.13.x before 1.13.1 transmits uninitialized interposer data to clients, which allows remote attackers to obtain sensitive information from process heap memory by sniffing the network for data in a handle field.

Project: krb5

badauth(OM_uint32 maj, OM_uint32 minor, SVCXPRT *xprt)
{
	if (log_badauth != NULL)
		(*log_badauth)(maj, minor, &xprt->xp_raddr, log_badauth_data);
	if (log_badauth2 != NULL)
		(*log_badauth2)(maj, minor, xprt, log_badauth2_data);
}

Project: krb5

svcauth_gss_acquire_cred(void)
{
	OM_uint32	maj_stat, min_stat;

	log_debug("in svcauth_gss_acquire_cred()");

	maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0,
				    GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
				    &svcauth_gss_creds, NULL, NULL);

	if (maj_stat != GSS_S_COMPLETE) {
		log_status("gss_acquire_cred", maj_stat, min_stat);
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5

svcauth_gss_destroy(SVCAUTH *auth)
{
	struct svc_rpc_gss_data	*gd;
	OM_uint32		 min_stat;

	log_debug("in svcauth_gss_destroy()");

	gd = SVCAUTH_PRIVATE(auth);

	gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER);
	gss_release_buffer(&min_stat, &gd->cname);
	gss_release_buffer(&min_stat, &gd->checksum);

	if (gd->client_name)
		gss_release_name(&min_stat, &gd->client_name);

	mem_free(gd, sizeof(*gd));
	mem_free(auth, sizeof(*auth));

	return (TRUE);
}

Project: krb5

svcauth_gss_get_principal(SVCAUTH *auth)
{
	struct svc_rpc_gss_data *gd;
	char *pname;

	gd = SVCAUTH_PRIVATE(auth);

	if (gd->cname.length == 0 || gd->cname.length >= SIZE_MAX)
		return (NULL);

	if ((pname = malloc(gd->cname.length + 1)) == NULL)
		return (NULL);

	memcpy(pname, gd->cname.value, gd->cname.length);
	pname[gd->cname.length] = '\0';

	return (pname);
}

Project: krb5

svcauth_gss_release_cred(void)
{
	OM_uint32	maj_stat, min_stat;

	log_debug("in svcauth_gss_release_cred()");

	maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds);

	if (maj_stat != GSS_S_COMPLETE) {
		log_status("gss_release_cred", maj_stat, min_stat);
		return (FALSE);
	}

	svcauth_gss_creds = NULL;

	return (TRUE);
}

Project: krb5

svcauth_gss_set_log_badauth2_func(auth_gssapi_log_badauth2_func func,
				  caddr_t data)
{
	log_badauth2 = func;
	log_badauth2_data = data;
}

Project: krb5

void svcauth_gss_set_log_badauth_func(
	auth_gssapi_log_badauth_func func,
	caddr_t data)
{
	log_badauth = func;
	log_badauth_data = data;
}

Project: krb5

void svcauth_gss_set_log_badverf_func(
	auth_gssapi_log_badverf_func func,
	caddr_t data)
{
	log_badverf = func;
	log_badverf_data = data;
}

Project: krb5

void svcauth_gss_set_log_miscerr_func(
	auth_gssapi_log_miscerr_func func,
	caddr_t data)
{
	log_miscerr = func;
	log_miscerr_data = data;
}

Project: krb5

svcauth_gss_set_svc_name(gss_name_t name)
{
	OM_uint32	maj_stat, min_stat;

	log_debug("in svcauth_gss_set_svc_name()");

	if (svcauth_gss_name != NULL) {
		maj_stat = gss_release_name(&min_stat, &svcauth_gss_name);

		if (maj_stat != GSS_S_COMPLETE) {
			log_status("gss_release_name", maj_stat, min_stat);
			return (FALSE);
		}
		svcauth_gss_name = NULL;
	}
	if (svcauth_gss_name == GSS_C_NO_NAME)
		return (TRUE);

	maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name);

	if (maj_stat != GSS_S_COMPLETE) {
		log_status("gss_duplicate_name", maj_stat, min_stat);
		return (FALSE);
	}

	return (TRUE);
}

Project: krb5

svcauth_gss_unwrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
	struct svc_rpc_gss_data	*gd;

	log_debug("in svcauth_gss_unwrap()");

	gd = SVCAUTH_PRIVATE(auth);

	if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
		return ((*xdr_func)(xdrs, xdr_ptr));
	}
	return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
				 gd->ctx, gd->sec.qop,
				 gd->sec.svc, gd->seq));
}