Commit message: Fix kadm5/gssrpc XDR double free [CVE-2014-9421]

[MITKRB5-SA-2015-001] In auth_gssapi_unwrap_data(), do not free
partial deserialization results upon failure to deserialize.  This
responsibility belongs to the callers, svctcp_getargs() and
svcudp_getargs(); doing it in the unwrap function results in freeing
the results twice.

In xdr_krb5_tl_data() and xdr_krb5_principal(), null out the pointers
we are freeing, as other XDR functions such as xdr_bytes() and
xdr_string().

ticket: 8056 (new)
target_version: 1.13.1
tags: pullup
CVE: CVE-2014-9421
CWE: CWE-703
Vulnerability description: The auth_gssapi_unwrap_data function in lib/rpc/auth_gssapi_misc.c in MIT Kerberos 5 (aka krb5) through 1.11.5, 1.12.x through 1.12.2, and 1.13.x before 1.13.1 does not properly handle partial XDR deserialization, which allows remote authenticated users to cause a denial of service (use-after-free and double free, and daemon crash) or possibly execute arbitrary code via malformed XDR data, as demonstrated by data sent to kadmind.

Project: krb5
File: kadm_rpc_xdr.c

_xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp, int vers)
{
	if (!xdr_nullstring(xdrs, &objp->policy)) {
		return (FALSE);
	}
	/* these all used to be u_int32, but it's stupid for sized types
	   to be exposed at the api, and they're the same as longs on the
	   wire. */
	if (!xdr_long(xdrs, &objp->pw_min_life)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->pw_max_life)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->pw_min_length)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->pw_min_classes)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->pw_history_num)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->policy_refcnt)) {
		return (FALSE);
	}
	if (xdrs->x_op == XDR_DECODE) {
		objp->pw_max_fail = 0;
		objp->pw_failcnt_interval = 0;
		objp->pw_lockout_duration = 0;
		objp->attributes = 0;
		objp->max_life = 0;
		objp->max_renewable_life = 0;
		objp->allowed_keysalts = NULL;
		objp->n_tl_data = 0;
		objp->tl_data = NULL;
	}
	if (vers >= KADM5_API_VERSION_3) {
		if (!xdr_krb5_kvno(xdrs, &objp->pw_max_fail))
			return (FALSE);
		if (!xdr_krb5_deltat(xdrs, &objp->pw_failcnt_interval))
			return (FALSE);
		if (!xdr_krb5_deltat(xdrs, &objp->pw_lockout_duration))
			return (FALSE);
	}
	if (vers >= KADM5_API_VERSION_4) {
		if (!xdr_krb5_flags(xdrs, &objp->attributes)) {
			return (FALSE);
		}
		if (!xdr_krb5_deltat(xdrs, &objp->max_life)) {
			return (FALSE);
		}
		if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) {
			return (FALSE);
		}
		if (!xdr_nullstring(xdrs, &objp->allowed_keysalts)) {
			return (FALSE);
		}
		if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) {
			return (FALSE);
		}
		if (!xdr_nulltype(xdrs, (void **) &objp->tl_data,
				  xdr_krb5_tl_data)) {
			return FALSE;
		}
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
			     int v)
{
	unsigned int n;

	if (!xdr_krb5_principal(xdrs, &objp->principal)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->princ_expire_time)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->last_pwd_change)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->pw_expiration)) {
		return (FALSE);
	}
	if (!xdr_krb5_deltat(xdrs, &objp->max_life)) {
		return (FALSE);
	}
	if (!xdr_nulltype(xdrs, (void **) &objp->mod_name,
			  xdr_krb5_principal)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->mod_date)) {
		return (FALSE);
	}
	if (!xdr_krb5_flags(xdrs, &objp->attributes)) {
		return (FALSE);
	}
	if (!xdr_krb5_kvno(xdrs, &objp->kvno)) {
		return (FALSE);
	}
	if (!xdr_krb5_kvno(xdrs, &objp->mkvno)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->policy)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->aux_attributes)) {
		return (FALSE);
	}
	if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->last_success)) {
		return (FALSE);
	}
	if (!xdr_krb5_timestamp(xdrs, &objp->last_failed)) {
		return (FALSE);
	}
	if (!xdr_krb5_kvno(xdrs, &objp->fail_auth_count)) {
		return (FALSE);
	}
	if (!xdr_krb5_int16(xdrs, &objp->n_key_data)) {
		return (FALSE);
	}
	if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) {
		return (FALSE);
	}
	if (!xdr_nulltype(xdrs, (void **) &objp->tl_data,
			  xdr_krb5_tl_data)) {
		return FALSE;
	}
	n = objp->n_key_data;
	if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
		       &n, ~0, sizeof(krb5_key_data),
		       xdr_krb5_key_data_nocontents)) {
		return (FALSE);
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_krb5_boolean(xdrs, &objp->keepold)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
		       (unsigned int*)&objp->n_ks_tuple, ~0,
		       sizeof(krb5_key_salt_tuple),
		       xdr_krb5_key_salt_tuple)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->pass)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_chpass_arg(XDR *xdrs, chpass_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->pass)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_krb5_boolean(xdrs, &objp->keepold)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
		       (unsigned int*)&objp->n_ks_tuple, ~0,
		       sizeof(krb5_key_salt_tuple),
		       xdr_krb5_key_salt_tuple)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_chrand_arg(XDR *xdrs, chrand_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_chrand_ret(XDR *xdrs, chrand_ret *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
		return (FALSE);
	}
	if (objp->code == KADM5_OK) {
		if (!xdr_array(xdrs, (char **)&objp->keys,
			       (unsigned int *)&objp->n_keys, ~0,
			       sizeof(krb5_keyblock), xdr_krb5_keyblock))
			return FALSE;
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_cpol_arg(XDR *xdrs, cpol_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
				       objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
					  objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple,
		       (unsigned int *)&objp->n_ks_tuple, ~0,
		       sizeof(krb5_key_salt_tuple),
		       xdr_krb5_key_salt_tuple)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->passwd)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
					  objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->passwd)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_dpol_arg(XDR *xdrs, dpol_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->name)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
     if (! xdr_kadm5_ret_t(xdrs, &objp->code) ||
	 ! xdr_long(xdrs, &objp->privs))
	  return FALSE;

     return TRUE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gpol_arg(XDR *xdrs, gpol_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->name)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
		return (FALSE);
	}
	if(objp->code == KADM5_OK) {
	    if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
					   objp->api_version))
		return (FALSE);
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gpols_arg(XDR *xdrs, gpols_arg *objp)
{
     if (!xdr_ui_4(xdrs, &objp->api_version)) {
	  return (FALSE);
     }
     if (!xdr_nullstring(xdrs, &objp->exp)) {
	  return (FALSE);
     }
     return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gpols_ret(XDR *xdrs, gpols_ret *objp)
{
     if (!xdr_ui_4(xdrs, &objp->api_version)) {
	  return (FALSE);
     }
     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
	  return (FALSE);
     }
     if (objp->code == KADM5_OK) {
	  if (!xdr_int(xdrs, &objp->count)) {
	       return (FALSE);
	  }
	  if (!xdr_array(xdrs, (caddr_t *) &objp->pols,
			 (unsigned int *) &objp->count, ~0,
			 sizeof(char *), xdr_nullstring)) {
	       return (FALSE);
	  }
     }

     return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
	     return FALSE;
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
		return (FALSE);
	}
	if(objp->code == KADM5_OK)  {
		if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
						  objp->api_version)) {
			return (FALSE);
		}
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp)
{
     if (!xdr_ui_4(xdrs, &objp->api_version)) {
	  return (FALSE);
     }
     if (!xdr_nullstring(xdrs, &objp->exp)) {
	  return (FALSE);
     }
     return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp)
{
     if (!xdr_ui_4(xdrs, &objp->api_version)) {
	  return (FALSE);
     }
     if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
	  return (FALSE);
     }
     if (objp->code == KADM5_OK) {
	  if (!xdr_int(xdrs, &objp->count)) {
	       return (FALSE);
	  }
	  if (!xdr_array(xdrs, (caddr_t *) &objp->princs,
			 (unsigned int *) &objp->count, ~0,
			 sizeof(char *), xdr_nullstring)) {
	       return (FALSE);
	  }
     }

     return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_gstrings_ret(XDR *xdrs, gstrings_ret *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
		return (FALSE);
	}
	if (objp->code == KADM5_OK) {
		if (!xdr_int(xdrs, &objp->count)) {
			return (FALSE);
		}
		if (!xdr_array(xdrs, (caddr_t *) &objp->strings,
			       (unsigned int *) &objp->count, ~0,
			       sizeof(krb5_string_attr),
			       xdr_krb5_string_attr)) {
			return (FALSE);
		}
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs,
				   kadm5_principal_ent_rec *objp)
{
     return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_3);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp)
{
	uint32_t tmp;

	if (xdrs->x_op == XDR_ENCODE)
		tmp = (uint32_t) *objp;

	if (!xdr_u_int32(xdrs, &tmp))
		return (FALSE);

	if (xdrs->x_op == XDR_DECODE)
		*objp = (kadm5_ret_t) tmp;

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

static bool_t xdr_krb5_boolean(XDR *xdrs, krb5_boolean *kbool)
{
	bool_t val;

	switch (xdrs->x_op) {
	case XDR_DECODE:
	     if (!xdr_bool(xdrs, &val))
		     return FALSE;

	     *kbool = (val == FALSE) ? FALSE : TRUE;
	     return TRUE;

	case XDR_ENCODE:
	     val = *kbool ? TRUE : FALSE;
	     return xdr_bool(xdrs, &val);

	case XDR_FREE:
	     return TRUE;
	}

	return FALSE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp)
{
  /* This assumes that int32 and krb5_deltat are the same size.
     This shouldn't be a problem, since we've got a unit test which
     checks for this. */
	if (!xdr_int32(xdrs, (int32_t *) objp)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp)
{
   /*
    * This used to be xdr_krb5_keytype, but keytypes and enctypes have
    * been merged into only enctypes.  However, randkey_principal
    * already ensures that only a key of ENCTYPE_DES_CBC_CRC will be
    * returned to v1 clients, and ENCTYPE_DES_CBC_CRC has the same
    * value as KEYTYPE_DES used too, which is what all v1 clients
    * expect.  Therefore, IMHO, just encoding whatever enctype we get
    * is safe.
    */

   if (!xdr_int32(xdrs, (int32_t *) objp))
	return (FALSE);
   return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_flags(XDR *xdrs, krb5_flags *objp)
{
  /* This assumes that int32 and krb5_flags are the same size.
     This shouldn't be a problem, since we've got a unit test which
     checks for this. */
	if (!xdr_int32(xdrs, (int32_t *) objp)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
{
    int tmp;

    tmp = (int) *objp;

    if (!xdr_int(xdrs, &tmp))
	return(FALSE);

    *objp = (krb5_int16) tmp;

    return(TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp)
{
     /*
      * Note that this function intentionally DOES NOT tranfer key
      * length or contents!  xdr_krb5_key_data in adb_xdr.c does, but
      * that is only for use within the server-side library.
      */
     unsigned int tmp;

     if (xdrs->x_op == XDR_DECODE)
	  memset(objp, 0, sizeof(krb5_key_data));

     if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) {
	  return (FALSE);
     }
     if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno)) {
	  return (FALSE);
     }
     if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) {
	  return (FALSE);
     }
     if (objp->key_data_ver > 1) {
	  if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1])) {
	       return (FALSE);
	  }
     }
     /*
      * kadm5_get_principal on the server side allocates and returns
      * key contents when asked.  Even though this function refuses to
      * transmit that data, it still has to *free* the data at the
      * appropriate time to avoid a memory leak.
      */
     if (xdrs->x_op == XDR_FREE) {
	  tmp = (unsigned int) objp->key_data_length[0];
	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
			 &tmp, ~0))
	       return FALSE;

	  tmp = (unsigned int) objp->key_data_length[1];
	  if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
			 &tmp, ~0))
	       return FALSE;
     }

     return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp)
{
    if (!xdr_krb5_enctype(xdrs, &objp->ks_enctype))
	return FALSE;
    if (!xdr_krb5_salttype(xdrs, &objp->ks_salttype))
	return FALSE;
    return TRUE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
{
	unsigned char tmp;

	tmp = '\0'; /* for purify, else xdr_u_char performs a umr */

	if (xdrs->x_op == XDR_ENCODE)
		tmp = (unsigned char) *objp;

	if (!xdr_u_char(xdrs, &tmp))
		return (FALSE);

	if (xdrs->x_op == XDR_DECODE)
		*objp = (krb5_kvno) tmp;

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp)
{
    if (!xdr_int32(xdrs, (int32_t *) objp))
	return FALSE;
    return TRUE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp)
{
	if (!xdr_nullstring(xdrs, &objp->key))
		return FALSE;
	if (!xdr_nullstring(xdrs, &objp->value))
		return FALSE;
	if (xdrs->x_op == XDR_DECODE &&
	    (objp->key == NULL || objp->value == NULL))
		return FALSE;
	return TRUE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp)
{
  /* This assumes that int32 and krb5_timestamp are the same size.
     This shouldn't be a problem, since we've got a unit test which
     checks for this. */
	if (!xdr_int32(xdrs, (int32_t *) objp)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
{
    unsigned int tmp;

    tmp = (unsigned int) *objp;

    if (!xdr_u_int(xdrs, &tmp))
	return(FALSE);

    *objp = (krb5_ui_2) tmp;

    return(TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp)
{
	if (!xdr_u_int32(xdrs, (uint32_t *) objp)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_mpol_arg(XDR *xdrs, mpol_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec,
				       objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec,
					  objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_long(xdrs, &objp->mask)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc)
{
     bool_t null;

     switch (xdrs->x_op) {
     case XDR_DECODE:
	  if (!xdr_bool(xdrs, &null))
	      return FALSE;
	  if (null) {
	       *objp = NULL;
	       return TRUE;
	  }
	  return (*proc)(xdrs, objp);

     case XDR_ENCODE:
	  if (*objp == NULL)
	       null = TRUE;
	  else
	       null = FALSE;
	  if (!xdr_bool(xdrs, &null))
	       return FALSE;
	  if (null == FALSE)
	       return (*proc)(xdrs, objp);
	  return TRUE;

     case XDR_FREE:
	  if (*objp)
	       return (*proc)(xdrs, objp);
	  return TRUE;
     }

     return FALSE;
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_purgekeys_arg(XDR *xdrs, purgekeys_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_int(xdrs, &objp->keepkvno)) {
	     return FALSE;
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->src)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->dest)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_krb5_boolean(xdrs, &objp->keepold)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *) &objp->ks_tuple,
		       (unsigned int *) &objp->n_ks_tuple, ~0,
		       sizeof(krb5_key_salt_tuple), xdr_krb5_key_salt_tuple)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
		       (unsigned int *) &objp->n_keys, ~0,
		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_setkey_arg(XDR *xdrs, setkey_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks,
		       (unsigned int *) &objp->n_keys, ~0,
		       sizeof(krb5_keyblock), xdr_krb5_keyblock)) {
		return (FALSE);
	}
	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

xdr_sstring_arg(XDR *xdrs, sstring_arg *objp)
{
	if (!xdr_ui_4(xdrs, &objp->api_version)) {
		return (FALSE);
	}
	if (!xdr_krb5_principal(xdrs, &objp->princ)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->key)) {
		return (FALSE);
	}
	if (!xdr_nullstring(xdrs, &objp->value)) {
		return (FALSE);
	}

	return (TRUE);
}

Project: krb5
File: kadm_rpc_xdr.c

bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp)
{
  /* Assumes that krb5_ui_4 and u_int32 are both four bytes long.
     This should not be a harmful assumption. */
  return xdr_u_int32(xdrs, (uint32_t *) objp);
}

Project: krb5
File: auth_gssapi_misc.c

static void auth_gssapi_display_status_1(
     char *m,
     OM_uint32 code,
     int type,
     int rec)
{
     OM_uint32 gssstat, minor_stat;
     gss_buffer_desc msg;
     OM_uint32 msg_ctx;

     msg_ctx = 0;
     while (1) {
	  gssstat = gss_display_status(&minor_stat, code,
				       type, GSS_C_NULL_OID,
				       &msg_ctx, &msg);
	  if (gssstat != GSS_S_COMPLETE) {
 	       if (!rec) {
		    auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1);
		    auth_gssapi_display_status_1(m, minor_stat,
						 GSS_C_MECH_CODE, 1);
	       } else {
		   fputs ("GSS-API authentication error ", stderr);
		   fwrite (msg.value, msg.length, 1, stderr);
		   fputs (": recursive failure!\n", stderr);
	       }
	       return;
	  }

	  fprintf (stderr, "GSS-API authentication error %s: ", m);
	  fwrite (msg.value, msg.length, 1, stderr);
	  putc ('\n', stderr);
	  if (misc_debug_gssapi)
	      gssrpcint_printf("GSS-API authentication error %s: %*s\n",
			       m, (int)msg.length, (char *) msg.value);
	  (void) gss_release_buffer(&minor_stat, &msg);

	  if (!msg_ctx)
	       break;
     }
}

Project: krb5
File: auth_gssapi_misc.c

bool_t auth_gssapi_seal_seq(
     gss_ctx_id_t context,
     uint32_t seq_num,
     gss_buffer_t out_buf)
{
     gss_buffer_desc in_buf;
     OM_uint32 gssstat, minor_stat;
     uint32_t nl_seq_num;

     nl_seq_num = htonl(seq_num);

     in_buf.length = sizeof(uint32_t);
     in_buf.value = (char *) &nl_seq_num;
     gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
			&in_buf, NULL, out_buf);
     if (gssstat != GSS_S_COMPLETE) {
	  PRINTF(("gssapi_seal_seq: failed\n"));
	  AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
				      gssstat, minor_stat));
	  return FALSE;
     }
     return TRUE;
}

Project: krb5
File: auth_gssapi_misc.c

bool_t auth_gssapi_wrap_data(
     OM_uint32 *major,
     OM_uint32 *minor,
     gss_ctx_id_t context,
     uint32_t seq_num,
     XDR *out_xdrs,
     bool_t (*xdr_func)(),
     caddr_t xdr_ptr)
{
     gss_buffer_desc in_buf, out_buf;
     XDR temp_xdrs;
     int conf_state;
     unsigned int length;

     PRINTF(("gssapi_wrap_data: starting\n"));

     *major = GSS_S_COMPLETE;
     *minor = 0; /* assumption */

     xdralloc_create(&temp_xdrs, XDR_ENCODE);

     /* serialize the sequence number into local memory */
     PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
     if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
	  PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
	  XDR_DESTROY(&temp_xdrs);
	  return FALSE;
     }

     /* serialize the arguments into local memory */
     if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
	  PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
	  XDR_DESTROY(&temp_xdrs);
	  return FALSE;
     }

     in_buf.length = xdr_getpos(&temp_xdrs);
     in_buf.value = xdralloc_getdata(&temp_xdrs);

     *major = gss_seal(minor, context, 1,
		       GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
		       &out_buf);
     if (*major != GSS_S_COMPLETE) {
	  XDR_DESTROY(&temp_xdrs);
	  return FALSE;
     }

     PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
	     (int) in_buf.length, (int) out_buf.length));

     /* write the token */
     length = out_buf.length;
     if (! xdr_bytes(out_xdrs, (char **) &out_buf.value,
		     (unsigned int *) &length,
		     out_buf.length)) {
	  PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
	  XDR_DESTROY(&temp_xdrs);
	  return FALSE;
     }

     *major = gss_release_buffer(minor, &out_buf);

     PRINTF(("gssapi_wrap_data: succeeding\n\n"));
     XDR_DESTROY(&temp_xdrs);
     return TRUE;
}

Project: krb5
File: auth_gssapi_misc.c

bool_t xdr_authgssapi_creds(
     XDR *xdrs,
     auth_gssapi_creds *creds)
{
     if (! xdr_u_int32(xdrs, &creds->version) ||
	 ! xdr_bool(xdrs, &creds->auth_msg) ||
	 ! xdr_gss_buf(xdrs, &creds->client_handle))
       return FALSE;
     return TRUE;
}

Project: krb5
File: auth_gssapi_misc.c

bool_t xdr_authgssapi_init_arg(
     XDR *xdrs,
     auth_gssapi_init_arg *init_arg)
{
     if (! xdr_u_int32(xdrs, &init_arg->version) ||
	 ! xdr_gss_buf(xdrs, &init_arg->token))
	  return FALSE;
     return TRUE;
}

Project: krb5
File: auth_gssapi_misc.c

bool_t xdr_authgssapi_init_res(
     XDR *xdrs,
     auth_gssapi_init_res *init_res)
{
     if (! xdr_u_int32(xdrs, &init_res->version) ||
	 ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
	 ! xdr_u_int32(xdrs, &init_res->gss_major) ||
	 ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
	 ! xdr_gss_buf(xdrs, &init_res->token) ||
	 ! xdr_gss_buf(xdrs, &init_res->signed_isn))
	  return FALSE;
     return TRUE;
}

Project: krb5
File: auth_gssapi_misc.c

bool_t xdr_gss_buf(
     XDR *xdrs,
     gss_buffer_t buf)
{
     /*
      * On decode, xdr_bytes will only allocate buf->value if the
      * length read in is < maxsize (last arg).  This is dumb, because
      * the whole point of allocating memory is so that I don't *have*
      * to know the maximum length.  -1 effectively disables this
      * braindamage.
      */
     bool_t result;
     /* Fix type mismatches between APIs.  */
     unsigned int length = buf->length;
     result = xdr_bytes(xdrs, (char **) &buf->value, &length,
			(xdrs->x_op == XDR_DECODE && buf->value == NULL)
			? (unsigned int) -1 : (unsigned int) buf->length);
     buf->length = length;
     return result;
}