| ↓ | gss_krb5_unwrap | 41 | 131 | 227 | krb5/msg.c | 
| 
OM_uint32
gss_krb5_unwrap (OM_uint32 * minor_status,
		 const gss_ctx_id_t context_handle,
		 const gss_buffer_t input_message_buffer,
		 gss_buffer_t output_message_buffer,
		 int *conf_state, gss_qop_t * qop_state)
{
  _gss_krb5_ctx_t k5 = context_handle->gt;krb5;
  gss_buffer_desc tok;
  char *data;
  OM_uint32 sgn_alg, seal_alg;
  size_t tmplen;
  int rc;
  rc = gss_decapsulate_token (input_message_buffer, GSS_KRB5, &tok);
  if (rc != GSS_S_COMPLETE)
    return GSS_S_BAD_MIC;
  if (tok.length gt;sh,
				      k5->gt;key,
				      0, SHISHI_DES_CBC_NONE,
				      cksum, 8, encseqno, 8, &tmp, &outlen);
	if (rc != SHISHI_OK)
	  return GSS_S_FAILURE;
	if (outlen != 8)
	  return GSS_S_BAD_MIC;
	memcpy (seqno, tmp, 8);
	free (tmp);
	if (memcmp (seqno + 4, k5->gt;acceptor ? "\x00\x00\x00\x00" :
		    "\xFF\xFF\xFF\xFF", 4) != 0)
	  return GSS_S_BAD_MIC;
	seqnr = C2I (seqno);
	if (seqnr != (k5->gt;acceptor ? k5->gt;initseqnr : k5->gt;acceptseqnr))
	  return GSS_S_BAD_MIC;
	if (k5->gt;acceptor)
	  k5->gt;initseqnr++;
	else
	  k5->gt;acceptseqnr++;
	/* Check pad */
	padlen = data[tok.length - 1];
	if (padlen >gt; 8)
	  return GSS_S_BAD_MIC;
	for (i = 1; i gt;sh,
			      k5->gt;key,
			      0, SHISHI_RSA_MD5_DES_GSS,
			      data + 16, tok.length - 16, &tmp, &tmplen);
	if (rc != SHISHI_OK || tmplen != 8)
	  return GSS_S_FAILURE;
	memcpy (data + 8, tmp, tmplen);
	/* Compare checksum */
	if (tmplen != 8 || memcmp (cksum, data + 8, 8) != 0)
	  return GSS_S_BAD_MIC;
	/* Copy output data */
	output_message_buffer->gt;length = tok.length - 8 - 8 - 8 - 8 - padlen;
	output_message_buffer->gt;value = malloc (output_message_buffer->gt;length);
	if (!output_message_buffer->gt;value)
	  {
	    if (minor_status)
	      *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	  }
	memcpy (output_message_buffer->gt;value, pt,
		tok.length - 4 * 8 - padlen);
      }
      break;
    case 4:			/* 3DES */
      {
	size_t padlen;
	char *p;
	char *t;
	char cksum[20];
	size_t outlen, i;
	uint32_t seqnr;
	if (tok.length gt;sh,
				      k5->gt;key,
				      0, SHISHI_DES3_CBC_NONE,
				      cksum, 8, p, 8, &t, &outlen);
	if (rc != SHISHI_OK || outlen != 8)
	  return GSS_S_FAILURE;
	memcpy (p, t, 8);
	free (t);
	if (memcmp (p + 4, k5->gt;acceptor ? "\x00\x00\x00\x00" :
		    "\xFF\xFF\xFF\xFF", 4) != 0)
	  return GSS_S_BAD_MIC;
	seqnr = C2I (p);
	if (seqnr != (k5->gt;acceptor ? k5->gt;initseqnr : k5->gt;acceptseqnr))
	  return GSS_S_BAD_MIC;
	if (k5->gt;acceptor)
	  k5->gt;initseqnr++;
	else
	  k5->gt;acceptseqnr++;
	/* Check pad */
	padlen = data[tok.length - 1];
	if (padlen >gt; 8)
	  return GSS_S_BAD_MIC;
	for (i = 1; i gt;sh,
			      k5->gt;key,
			      SHISHI_KEYUSAGE_GSS_R2,
			      SHISHI_HMAC_SHA1_DES3_KD, data + 20 + 8,
			      tok.length - 20 - 8, &t, &tmplen);
	if (rc != SHISHI_OK || tmplen != 20)
	  return GSS_S_FAILURE;
	memcpy (data + 8 + 8, t, tmplen);
	free (t);
	/* Compare checksum */
	if (tmplen != 20 || memcmp (cksum, data + 8 + 8, 20) != 0)
	  return GSS_S_BAD_MIC;
	/* Copy output data */
	output_message_buffer->gt;length = tok.length - 8 - 20 - 8 - 8 - padlen;
	output_message_buffer->gt;value = malloc (output_message_buffer->gt;length);
	if (!output_message_buffer->gt;value)
	  {
	    if (minor_status)
	      *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	  }
	memcpy (output_message_buffer->gt;value, data + 20 + 8 + 8 + 8,
		tok.length - 20 - 8 - 8 - 8 - padlen);
      }
      break;
    default:
      return GSS_S_FAILURE;
    }
  return GSS_S_COMPLETE;
}
 | 
| ↓ | gss_krb5_accept_sec_context | 30 | 100 | 190 | krb5/context.c | 
| 
OM_uint32
gss_krb5_accept_sec_context (OM_uint32 * minor_status,
			     gss_ctx_id_t * context_handle,
			     const gss_cred_id_t acceptor_cred_handle,
			     const gss_buffer_t input_token_buffer,
			     const gss_channel_bindings_t input_chan_bindings,
			     gss_name_t * src_name,
			     gss_OID * mech_type,
			     gss_buffer_t output_token,
			     OM_uint32 * ret_flags,
			     OM_uint32 * time_rec,
			     gss_cred_id_t * delegated_cred_handle)
{
  gss_buffer_desc in;
  gss_ctx_id_t cx;
  _gss_krb5_ctx_t cxk5;
  _gss_krb5_cred_t crk5;
  OM_uint32 tmp_min_stat;
  int rc;
  if (minor_status)
    *minor_status = 0;
  if (ret_flags)
    *ret_flags = 0;
  if (!acceptor_cred_handle)
    /* XXX support GSS_C_NO_CREDENTIAL: acquire_cred() default server */
    return GSS_S_NO_CRED;
  if (*context_handle)
    return GSS_S_FAILURE;
  crk5 = acceptor_cred_handle->gt;krb5;
  cx = calloc (sizeof (*cx), 1);
  if (!cx)
    {
      if (minor_status)
	*minor_status = ENOMEM;
      return GSS_S_FAILURE;
    }
  cxk5 = calloc (sizeof (*cxk5), 1);
  if (!cxk5)
    {
      free (cx);
      if (minor_status)
	*minor_status = ENOMEM;
      return GSS_S_FAILURE;
    }
  cx->gt;mech = GSS_KRB5;
  cx->gt;krb5 = cxk5;
  /* XXX cx->gt;peer?? */
  *context_handle = cx;
  cxk5->gt;sh = crk5->gt;sh;
  cxk5->gt;key = crk5->gt;key;
  cxk5->gt;acceptor = 1;
  rc = shishi_ap (cxk5->gt;sh, &cxk5->gt;ap);
  if (rc != SHISHI_OK)
    return GSS_S_FAILURE;
  rc = gss_decapsulate_token (input_token_buffer, GSS_KRB5, &in);
  if (rc != GSS_S_COMPLETE)
    return GSS_S_BAD_MIC;
  if (in.length gt;ap, (char *) in.value + TOK_LEN,
			      in.length - TOK_LEN);
  gss_release_buffer (&tmp_min_stat, &in);
  if (rc != SHISHI_OK)
    return GSS_S_FAILURE;
  rc = shishi_ap_req_process (cxk5->gt;ap, crk5->gt;key);
  if (rc != SHISHI_OK)
    {
      if (minor_status)
	*minor_status = GSS_KRB5_S_G_VALIDATE_FAILED;
      return GSS_S_FAILURE;
    }
  rc = shishi_authenticator_seqnumber_get (cxk5->gt;sh,
					   shishi_ap_authenticator (cxk5->gt;ap),
					   &cxk5->gt;initseqnr);
  if (rc != SHISHI_OK)
    return GSS_S_FAILURE;
  rc = _gss_krb5_checksum_parse (minor_status,
				 context_handle, input_chan_bindings);
  if (rc != GSS_S_COMPLETE)
    return GSS_S_FAILURE;
  cxk5->gt;tkt = shishi_ap_tkt (cxk5->gt;ap);
  cxk5->gt;key = shishi_ap_key (cxk5->gt;ap);
  if (shishi_apreq_mutual_required_p (crk5->gt;sh, shishi_ap_req (cxk5->gt;ap)))
    {
      Shishi_asn1 aprep;
      char *der;
      size_t len;
      rc = shishi_ap_rep_asn1 (cxk5->gt;ap, &aprep);
      if (rc != SHISHI_OK)
	{
	  printf ("Error creating AP-REP: %s\n", shishi_strerror (rc));
	  return GSS_S_FAILURE;
	}
      rc = shishi_encapreppart_seqnumber_get (cxk5->gt;sh,
					      shishi_ap_encapreppart
					      (cxk5->gt;ap), &cxk5->gt;acceptseqnr);
      if (rc != SHISHI_OK)
	{
	  /* A strict 1964 implementation would return
	     GSS_S_DEFECTIVE_TOKEN here.  gssapi-cfx permit absent
	     sequence number, though. */
	  cxk5->gt;acceptseqnr = 0;
	}
      rc = shishi_asn1_to_der (crk5->gt;sh, aprep, &der, &len);
      if (rc != SHISHI_OK)
	{
	  printf ("Error der encoding aprep: %s\n", shishi_strerror (rc));
	  return GSS_S_FAILURE;
	}
      rc = _gss_encapsulate_token_prefix (TOK_AP_REP, TOK_LEN,
					  der, len,
					  GSS_KRB5->gt;elements,
					  GSS_KRB5->gt;length,
					  &output_token->gt;value,
					  &output_token->gt;length);
      if (rc != 0)
	return GSS_S_FAILURE;
      if (ret_flags)
	*ret_flags = GSS_C_MUTUAL_FLAG;
    }
  else
    {
      output_token->gt;value = NULL;
      output_token->gt;length = 0;
    }
  if (src_name)
    {
      gss_name_t p;
      p = malloc (sizeof (*p));
      if (!p)
	{
	  if (minor_status)
	    *minor_status = ENOMEM;
	  return GSS_S_FAILURE;
	}
      rc = shishi_encticketpart_client (cxk5->gt;sh,
					shishi_tkt_encticketpart (cxk5->gt;tkt),
					&p->gt;value, &p->gt;length);
      if (rc != SHISHI_OK)
	return GSS_S_FAILURE;
      p->gt;type = GSS_KRB5_NT_PRINCIPAL_NAME;
      *src_name = p;
    }
  /* PROT_READY is not mentioned in 1964/gssapi-cfx but we support
     it anyway. */
  if (ret_flags)
    *ret_flags |= GSS_C_PROT_READY_FLAG;
  if (minor_status)
    *minor_status = 0;
  return GSS_S_COMPLETE;
}
 | 
| ↓ | gss_display_status | 23 | 67 | 157 | error.c | 
| 
OM_uint32
gss_display_status (OM_uint32 * minor_status,
		    OM_uint32 status_value,
		    int status_type,
		    const gss_OID mech_type,
		    OM_uint32 * message_context, gss_buffer_t status_string)
{
  size_t i;
  bindtextdomain (PACKAGE PO_SUFFIX, LOCALEDIR);
  if (minor_status)
    *minor_status = 0;
  if (message_context)
    status_value &= ~*message_context;
  switch (status_type)
    {
    case GSS_C_GSS_CODE:
      if (message_context)
	{
	  *message_context |=
	    GSS_C_ROUTINE_ERROR_MASK gt;value =
	    strdup (_(gss_routine_errors
		      [(GSS_ROUTINE_ERROR (status_value) >gt;>gt;
			GSS_C_ROUTINE_ERROR_OFFSET) - 1].text));
	  if (!status_string->gt;value)
	    {
	      if (minor_status)
		*minor_status = ENOMEM;
	      return GSS_S_FAILURE;
	    }
	  status_string->gt;length = strlen (status_string->gt;value);
	  return GSS_S_COMPLETE;
	  break;
	default:
	  return GSS_S_BAD_STATUS;
	  break;
	}
      if (message_context)
	{
	  *message_context |=
	    GSS_C_CALLING_ERROR_MASK gt;value =
	    strdup (_(gss_calling_errors
		      [(GSS_CALLING_ERROR (status_value) >gt;>gt;
			GSS_C_CALLING_ERROR_OFFSET) - 1].text));
	  if (!status_string->gt;value)
	    {
	      if (minor_status)
		*minor_status = ENOMEM;
	      return GSS_S_FAILURE;
	    }
	  status_string->gt;length = strlen (status_string->gt;value);
	  return GSS_S_COMPLETE;
	  break;
	default:
	  return GSS_S_BAD_STATUS;
	  break;
	}
      for (i = 0; i gt;value =
	      strdup (_(gss_supplementary_errors[i].text));
	    if (!status_string->gt;value)
	      {
		if (minor_status)
		  *minor_status = ENOMEM;
		return GSS_S_FAILURE;
	      }
	    status_string->gt;length = strlen (status_string->gt;value);
	    *message_context |= gss_supplementary_errors[i].err;
	    if ((status_value & ~*message_context) == 0)
	      *message_context = 0;
	    return GSS_S_COMPLETE;
	  }
      if (GSS_SUPPLEMENTARY_INFO (status_value))
	return GSS_S_BAD_STATUS;
      if (message_context)
	*message_context = 0;
      status_string->gt;value = strdup (_("No error"));
      if (!status_string->gt;value)
	{
	  if (minor_status)
	    *minor_status = ENOMEM;
	  return GSS_S_FAILURE;
	}
      status_string->gt;length = strlen (status_string->gt;value);
      break;
    case GSS_C_MECH_CODE:
      {
	_gss_mech_api_t mech;
	mech = _gss_find_mech (mech_type);
	return mech->gt;display_status (minor_status, status_value, status_type,
				     mech_type, message_context,
				     status_string);
      }
      break;
    default:
      return GSS_S_BAD_STATUS;
    }
  return GSS_S_COMPLETE;
}
 | 
| ↓ | gss_krb5_wrap | 22 | 112 | 213 | krb5/msg.c | 
| 
OM_uint32
gss_krb5_wrap (OM_uint32 * minor_status,
	       const gss_ctx_id_t context_handle,
	       int conf_req_flag,
	       gss_qop_t qop_req,
	       const gss_buffer_t input_message_buffer,
	       int *conf_state, gss_buffer_t output_message_buffer)
{
  _gss_krb5_ctx_t k5 = context_handle->gt;krb5;
  size_t padlength;
  gss_buffer_desc data;
  char *p;
  size_t tmplen;
  int rc;
  switch (shishi_key_type (k5->gt;key))
    {
      /* XXX implement other checksums */
    case SHISHI_DES_CBC_MD5:
      {
	char header[8];
	char seqno[8];
	char *eseqno;
	char *cksum;
	char confounder[8];
	/* Typical data:
	   ;; 02 01 00 00 ff ff ff ff  0c 22 1f 79 59 3d 00 cb
	   ;; d5 78 2f fb 50 d2 b8 59  fb b4 e0 9b d0 a2 fa dc
	   ;; 01 00 20 00 04 04 04 04
	   Translates into:
	   ;;   HEADER                 ENCRYPTED SEQ.NUMBER
	   ;;   DES-MAC-MD5 CKSUM      CONFOUNDER
	   ;;   PADDED DATA
	 */
	padlength = 8 - input_message_buffer->gt;length % 8;
	data.length = 4 * 8 + input_message_buffer->gt;length + padlength;
	p = malloc (data.length);
	if (!p)
	  {
	    if (minor_status)
	      *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	  }
	/* XXX encrypt data iff confidential option chosen */
	/* Setup header and confounder */
	memcpy (header, TOK_WRAP, 2);	/* TOK_ID: Wrap 0201 */
	memcpy (header + 2, "\x00\x00", 2);	/* SGN_ALG: DES-MAC-MD5 */
	memcpy (header + 4, "\xFF\xFF", 2);	/* SEAL_ALG: none */
	memcpy (header + 6, "\xFF\xFF", 2);	/* filler */
	rc = shishi_randomize (k5->gt;sh, 0, confounder, 8);
	if (rc != SHISHI_OK)
	  return GSS_S_FAILURE;
	/* Compute checksum over header, confounder, input string, and pad */
	memcpy (p, header, 8);
	memcpy (p + 8, confounder, 8);
	memcpy (p + 16, input_message_buffer->gt;value,
		input_message_buffer->gt;length);
	memset (p + 16 + input_message_buffer->gt;length,
		(int) padlength, padlength);
	rc = shishi_checksum (k5->gt;sh,
			      k5->gt;key,
			      0, SHISHI_RSA_MD5_DES_GSS,
			      p,
			      16 + input_message_buffer->gt;length + padlength,
			      &cksum, &tmplen);
	if (rc != SHISHI_OK || tmplen != 8)
	  return GSS_S_FAILURE;
	/* seq_nr */
	if (k5->gt;acceptor)
	  {
	    seqno[0] = k5->gt;acceptseqnr & 0xFF;
	    seqno[1] = k5->gt;acceptseqnr >gt;>gt; 8 & 0xFF;
	    seqno[2] = k5->gt;acceptseqnr >gt;>gt; 16 & 0xFF;
	    seqno[3] = k5->gt;acceptseqnr >gt;>gt; 24 & 0xFF;
	    memset (seqno + 4, 0xFF, 4);
	  }
	else
	  {
	    seqno[0] = k5->gt;initseqnr & 0xFF;
	    seqno[1] = k5->gt;initseqnr >gt;>gt; 8 & 0xFF;
	    seqno[2] = k5->gt;initseqnr >gt;>gt; 16 & 0xFF;
	    seqno[3] = k5->gt;initseqnr >gt;>gt; 24 & 0xFF;
	    memset (seqno + 4, 0, 4);
	  }
	rc = shishi_encrypt_iv_etype (k5->gt;sh, k5->gt;key, 0,
				      SHISHI_DES_CBC_NONE, cksum, 8,
				      seqno, 8, &eseqno, &tmplen);
	if (rc != SHISHI_OK || tmplen != 8)
	  return GSS_S_FAILURE;
	/* put things in place */
	memcpy (p, header, 8);
	memcpy (p + 8, eseqno, 8);
	free (eseqno);
	memcpy (p + 16, cksum, 8);
	free (cksum);
	memcpy (p + 24, confounder, 8);
	memcpy (p + 32, input_message_buffer->gt;value,
		input_message_buffer->gt;length);
	memset (p + 32 + input_message_buffer->gt;length,
		(int) padlength, padlength);
	data.value = p;
	rc = gss_encapsulate_token (&data, GSS_KRB5, output_message_buffer);
	if (rc != GSS_S_COMPLETE)
	  return GSS_S_FAILURE;
	if (k5->gt;acceptor)
	  k5->gt;acceptseqnr++;
	else
	  k5->gt;initseqnr++;
      }
      break;
    case SHISHI_DES3_CBC_HMAC_SHA1_KD:
      {
	char *tmp;
	padlength = 8 - input_message_buffer->gt;length % 8;
	data.length = 8 + 8 + 20 + 8 + input_message_buffer->gt;length
	  + padlength;
	p = malloc (data.length);
	if (!p)
	  {
	    if (minor_status)
	      *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	  }
	/* XXX encrypt data iff confidential option chosen */
	/* Compute checksum over header, confounder, input string, and pad */
	memcpy (p, TOK_WRAP, 2);	/* TOK_ID: Wrap */
	memcpy (p + 2, "\x04\x00", 2);	/* SGN_ALG: 3DES */
	memcpy (p + 4, "\xFF\xFF", 2);	/* SEAL_ALG: none */
	memcpy (p + 6, "\xFF\xFF", 2);	/* filler */
	rc = shishi_randomize (k5->gt;sh, 0, p + 8, 8);
	if (rc != SHISHI_OK)
	  return GSS_S_FAILURE;
	memcpy (p + 16, input_message_buffer->gt;value,
		input_message_buffer->gt;length);
	memset (p + 16 + input_message_buffer->gt;length,
		(int) padlength, padlength);
	rc = shishi_checksum (k5->gt;sh,
			      k5->gt;key,
			      SHISHI_KEYUSAGE_GSS_R2,
			      SHISHI_HMAC_SHA1_DES3_KD, p,
			      16 + input_message_buffer->gt;length + padlength,
			      &tmp, &tmplen);
	if (rc != SHISHI_OK || tmplen != 20)
	  return GSS_S_FAILURE;
	memcpy (p + 16, tmp, tmplen);
	memcpy (p + 36, p + 8, 8);
	/* seq_nr */
	if (k5->gt;acceptor)
	  {
	    (p + 8)[0] = k5->gt;acceptseqnr & 0xFF;
	    (p + 8)[1] = k5->gt;acceptseqnr >gt;>gt; 8 & 0xFF;
	    (p + 8)[2] = k5->gt;acceptseqnr >gt;>gt; 16 & 0xFF;
	    (p + 8)[3] = k5->gt;acceptseqnr >gt;>gt; 24 & 0xFF;
	    memset (p + 8 + 4, 0xFF, 4);
	  }
	else
	  {
	    (p + 8)[0] = k5->gt;initseqnr & 0xFF;
	    (p + 8)[1] = k5->gt;initseqnr >gt;>gt; 8 & 0xFF;
	    (p + 8)[2] = k5->gt;initseqnr >gt;>gt; 16 & 0xFF;
	    (p + 8)[3] = k5->gt;initseqnr >gt;>gt; 24 & 0xFF;
	    memset (p + 8 + 4, 0, 4);
	  }
	rc = shishi_encrypt_iv_etype (k5->gt;sh, k5->gt;key, 0, SHISHI_DES3_CBC_NONE, p + 16, 8,	/* cksum */
				      p + 8, 8, &tmp, &tmplen);
	if (rc != SHISHI_OK || tmplen != 8)
	  return GSS_S_FAILURE;
	memcpy (p + 8, tmp, tmplen);
	free (tmp);
	memcpy (p + 8 + 8 + 20 + 8, input_message_buffer->gt;value,
		input_message_buffer->gt;length);
	memset (p + 8 + 8 + 20 + 8 + input_message_buffer->gt;length,
		(int) padlength, padlength);
	data.value = p;
	rc = gss_encapsulate_token (&data, GSS_KRB5, output_message_buffer);
	if (rc != GSS_S_COMPLETE)
	  return GSS_S_FAILURE;
	if (k5->gt;acceptor)
	  k5->gt;acceptseqnr++;
	else
	  k5->gt;initseqnr++;
	break;
      }
    default:
      return GSS_S_FAILURE;
    }
  return GSS_S_COMPLETE;
}
 | 
| ↓ | gss_krb5_init_sec_context | 17 | 40 | 112 | krb5/context.c | 
| 
OM_uint32
gss_krb5_init_sec_context (OM_uint32 * minor_status,
			   const gss_cred_id_t initiator_cred_handle,
			   gss_ctx_id_t * context_handle,
			   const gss_name_t target_name,
			   const gss_OID mech_type,
			   OM_uint32 req_flags,
			   OM_uint32 time_req,
			   const gss_channel_bindings_t input_chan_bindings,
			   const gss_buffer_t input_token,
			   gss_OID * actual_mech_type,
			   gss_buffer_t output_token,
			   OM_uint32 * ret_flags, OM_uint32 * time_rec)
{
  gss_ctx_id_t ctx = *context_handle;
  _gss_krb5_ctx_t k5 = ctx->gt;krb5;
  OM_uint32 maj_stat;
  int rc;
  if (minor_status)
    *minor_status = 0;
  if (initiator_cred_handle)
    {
      /* We only support the default initiator.  See k5internal.h for
         adding a Shishi_tkt to the credential structure.  I'm not sure
         what the use would be -- user-to-user authentication perhaps?
         Later: if you have tickets for foo@BAR and bar@FOO, it may be
         useful to call gss_acquire_cred first to chose which one to
         initiate the context with.  Not many applications need this. */
      return GSS_S_NO_CRED;
    }
  if (target_name == NULL)
    {
      return GSS_S_BAD_NAME;
    }
  if (k5 == NULL)
    {
      k5 = ctx->gt;krb5 = calloc (sizeof (*k5), 1);
      if (!k5)
	{
	  if (minor_status)
	    *minor_status = ENOMEM;
	  return GSS_S_FAILURE;
	}
      rc = shishi_init (&k5->gt;sh);
      if (rc != SHISHI_OK)
	return GSS_S_FAILURE;
    }
  if (!k5->gt;reqdone)
    {
      maj_stat = init_request (minor_status,
			       initiator_cred_handle,
			       context_handle,
			       target_name,
			       mech_type,
			       req_flags,
			       time_req,
			       input_chan_bindings,
			       input_token,
			       actual_mech_type,
			       output_token, ret_flags, time_rec);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
      k5->gt;flags = req_flags & (	/* GSS_C_DELEG_FLAG | */
				GSS_C_MUTUAL_FLAG |
				GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG |
				GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG);
      /* PROT_READY is not mentioned in 1964/gssapi-cfx but we support
         it anyway. */
      k5->gt;flags |= GSS_C_PROT_READY_FLAG;
      if (ret_flags)
	*ret_flags = k5->gt;flags;
      k5->gt;key = shishi_ap_key (k5->gt;ap);
      k5->gt;reqdone = 1;
    }
  else if (k5->gt;reqdone && k5->gt;flags & GSS_C_MUTUAL_FLAG && !k5->gt;repdone)
    {
      maj_stat = init_reply (minor_status,
			     initiator_cred_handle,
			     context_handle,
			     target_name,
			     mech_type,
			     req_flags,
			     time_req,
			     input_chan_bindings,
			     input_token,
			     actual_mech_type,
			     output_token, ret_flags, time_rec);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
      if (ret_flags)
	*ret_flags = k5->gt;flags;
      k5->gt;repdone = 1;
    }
  else
    maj_stat = GSS_S_FAILURE;
  if (time_rec)
    *time_rec = gss_krb5_tktlifetime (k5->gt;tkt);
  return maj_stat;
}
 | 
| ↓ | gss_init_sec_context | 16 | 38 | 88 | context.c | 
| 
OM_uint32
gss_init_sec_context (OM_uint32 * minor_status,
		      const gss_cred_id_t initiator_cred_handle,
		      gss_ctx_id_t * context_handle,
		      const gss_name_t target_name,
		      const gss_OID mech_type,
		      OM_uint32 req_flags,
		      OM_uint32 time_req,
		      const gss_channel_bindings_t input_chan_bindings,
		      const gss_buffer_t input_token,
		      gss_OID * actual_mech_type,
		      gss_buffer_t output_token,
		      OM_uint32 * ret_flags, OM_uint32 * time_rec)
{
  OM_uint32 maj_stat;
  _gss_mech_api_t mech;
  int freecontext = 0;
  if (output_token)
    {
      output_token->gt;length = 0;
      output_token->gt;value = NULL;
    }
  if (ret_flags)
    *ret_flags = 0;
  if (!context_handle)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_NO_CONTEXT | GSS_S_CALL_INACCESSIBLE_READ;
    }
  if (output_token == GSS_C_NO_BUFFER)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE;
    }
  if (*context_handle == GSS_C_NO_CONTEXT)
    mech = _gss_find_mech (mech_type);
  else
    mech = _gss_find_mech ((*context_handle)->gt;mech);
  if (mech == NULL)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_BAD_MECH;
    }
  if (actual_mech_type)
    *actual_mech_type = mech->gt;mech;
  if (*context_handle == GSS_C_NO_CONTEXT)
    {
      *context_handle = calloc (sizeof (**context_handle), 1);
      if (!*context_handle)
	{
	  if (minor_status)
	    *minor_status = ENOMEM;
	  return GSS_S_FAILURE;
	}
      (*context_handle)->gt;mech = mech->gt;mech;
      freecontext = 1;
    }
  maj_stat = mech->gt;init_sec_context (minor_status,
				     initiator_cred_handle,
				     context_handle,
				     target_name,
				     mech_type,
				     req_flags,
				     time_req,
				     input_chan_bindings,
				     input_token,
				     actual_mech_type,
				     output_token, ret_flags, time_rec);
  if (GSS_ERROR (maj_stat) && freecontext)
    {
      free (*context_handle);
      *context_handle = GSS_C_NO_CONTEXT;
    }
  return maj_stat;
}
 | 
| ↓ | gss_krb5_canonicalize_name | 14 | 40 | 83 | krb5/name.c | 
| 
OM_uint32
gss_krb5_canonicalize_name (OM_uint32 * minor_status,
			    const gss_name_t input_name,
			    const gss_OID mech_type, gss_name_t * output_name)
{
  OM_uint32 maj_stat;
  if (minor_status)
    *minor_status = 0;
  /* We consider (a zero terminated) GSS_KRB5_NT_PRINCIPAL_NAME the
     canonical mechanism name type.  Convert everything into it.  */
  if (gss_oid_equal (input_name->gt;type, GSS_C_NT_EXPORT_NAME))
    {
      if (input_name->gt;length >gt; 15)
	{
	  *output_name = malloc (sizeof (**output_name));
	  if (!*output_name)
	    {
	      if (minor_status)
		*minor_status = ENOMEM;
	      return GSS_S_FAILURE;
	    }
	  (*output_name)->gt;type = GSS_KRB5_NT_PRINCIPAL_NAME;
	  (*output_name)->gt;length = input_name->gt;length - 15;
	  (*output_name)->gt;value = malloc ((*output_name)->gt;length + 1);
	  if (!(*output_name)->gt;value)
	    {
	      free (*output_name);
	      if (minor_status)
		*minor_status = ENOMEM;
	      return GSS_S_FAILURE;
	    }
	  memcpy ((*output_name)->gt;value, input_name->gt;value + 15,
		  (*output_name)->gt;length);
	  (*output_name)->gt;value[(*output_name)->gt;length] = '\0';
	}
      else
	{
	  return GSS_S_BAD_NAME;
	}
    }
  else if (gss_oid_equal (input_name->gt;type, GSS_C_NT_HOSTBASED_SERVICE))
    {
      char *p;
      /* We don't support service-names without hostname part because
         we can't compute a canonicalized name of the local host.
         Calling gethostname does not give a canonicalized name. */
      if (!memchr (input_name->gt;value, '@', input_name->gt;length))
	{
	  *minor_status = GSS_KRB5_S_G_BAD_SERVICE_NAME;
	  return GSS_S_COMPLETE;
	}
      /* We don't do DNS name canoncalization since that is
         insecure. */
      maj_stat = gss_duplicate_name (minor_status, input_name, output_name);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
      (*output_name)->gt;type = GSS_KRB5_NT_PRINCIPAL_NAME;
      p = memchr ((*output_name)->gt;value, '@', (*output_name)->gt;length);
      if (p)
	*p = '/';
    }
  else if (gss_oid_equal (input_name->gt;type, GSS_KRB5_NT_PRINCIPAL_NAME))
    {
      maj_stat = gss_duplicate_name (minor_status, input_name, output_name);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
    }
  else
    {
      *output_name = GSS_C_NO_NAME;
      return GSS_S_BAD_NAMETYPE;
    }
  return GSS_S_COMPLETE;
}
 | 
| ↓ | gss_add_oid_set_member | 13 | 29 | 56 | misc.c | 
| 
OM_uint32
gss_add_oid_set_member (OM_uint32 * minor_status,
			const gss_OID member_oid, gss_OID_set * oid_set)
{
  OM_uint32 major_stat;
  int present;
  if (!member_oid || member_oid->gt;length == 0 || member_oid->gt;elements == NULL)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_FAILURE;
    }
  major_stat = gss_test_oid_set_member (minor_status, member_oid,
					*oid_set, &present);
  if (GSS_ERROR (major_stat))
    return major_stat;
  if (present)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_COMPLETE;
    }
  if ((*oid_set)->gt;count + 1 == 0)	/* integer overflow */
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_FAILURE;
    }
  (*oid_set)->gt;count++;
  {
    gss_OID tmp;
    tmp = realloc ((*oid_set)->gt;elements, (*oid_set)->gt;count *
		   sizeof (*(*oid_set)->gt;elements));
    if (!tmp)
      {
	if (minor_status)
	  *minor_status = ENOMEM;
	return GSS_S_FAILURE;
      }
    (*oid_set)->gt;elements = tmp;
  }
  major_stat = _gss_copy_oid (minor_status, member_oid,
			      (*oid_set)->gt;elements + ((*oid_set)->gt;count - 1));
  if (GSS_ERROR (major_stat))
    return major_stat;
  return GSS_S_COMPLETE;
}
 | 
| ↓ | acquire_cred1 | 12 | 35 | 69 | krb5/cred.c | 
| 
static OM_uint32
acquire_cred1 (OM_uint32 * minor_status,
	       const gss_name_t desired_name,
	       OM_uint32 time_req,
	       const gss_OID_set desired_mechs,
	       gss_cred_usage_t cred_usage,
	       gss_cred_id_t * output_cred_handle,
	       gss_OID_set * actual_mechs, OM_uint32 * time_rec)
{
  gss_name_t name = desired_name;
  _gss_krb5_cred_t k5 = (*output_cred_handle)->gt;krb5;
  OM_uint32 maj_stat;
  if (desired_name == GSS_C_NO_NAME)
    {
      gss_buffer_desc buf = { 4, (char *) "host" };
      maj_stat = gss_import_name (minor_status, &buf,
				  GSS_C_NT_HOSTBASED_SERVICE, &name);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
    }
  maj_stat = gss_krb5_canonicalize_name (minor_status, name,
					 GSS_KRB5, &k5->gt;peerptr);
  if (GSS_ERROR (maj_stat))
    return maj_stat;
  if (k5->gt;peerptr == GSS_C_NO_NAME)
    {
      maj_stat = gss_release_name (minor_status, &name);
      if (GSS_ERROR (maj_stat))
	return maj_stat;
      return GSS_S_BAD_NAME;
    }
  if (shishi_init_server (&k5->gt;sh) != SHISHI_OK)
    return GSS_S_FAILURE;
  {
    char *p;
    p = malloc (k5->gt;peerptr->gt;length + 1);
    if (!p)
      {
	if (minor_status)
	  *minor_status = ENOMEM;
	return GSS_S_FAILURE;
      }
    memcpy (p, k5->gt;peerptr->gt;value, k5->gt;peerptr->gt;length);
    p[k5->gt;peerptr->gt;length] = 0;
    k5->gt;key = shishi_hostkeys_for_serverrealm (k5->gt;sh, p, NULL);
    free (p);
  }
  if (!k5->gt;key)
    {
      if (minor_status)
	*minor_status = GSS_KRB5_S_KG_KEYTAB_NOMATCH;
      return GSS_S_NO_CRED;
    }
  if (time_rec)
    *time_rec = GSS_C_INDEFINITE;
  return GSS_S_COMPLETE;
}
 | 
| ↓ | _gss_krb5_checksum_parse | 11 | 39 | 72 | krb5/checksum.c | 
| 
OM_uint32
_gss_krb5_checksum_parse (OM_uint32 * minor_status,
			  gss_ctx_id_t * context_handle,
			  const gss_channel_bindings_t input_chan_bindings)
{
  gss_ctx_id_t ctx = *context_handle;
  _gss_krb5_ctx_t k5 = ctx->gt;krb5;
  char *out = NULL;
  size_t len = 0;
  int rc;
  char *md5hash;
  if (shishi_ap_authenticator_cksumtype (k5->gt;ap) != 0x8003)
    {
      if (minor_status)
	*minor_status = GSS_KRB5_S_G_VALIDATE_FAILED;
      return GSS_S_FAILURE;
    }
  rc = shishi_ap_authenticator_cksumdata (k5->gt;ap, out, &len);
  if (rc != SHISHI_TOO_SMALL_BUFFER)
    return GSS_S_FAILURE;
  out = malloc (len);
  if (!out)
    {
      if (minor_status)
	*minor_status = ENOMEM;
      return GSS_S_FAILURE;
    }
  rc = shishi_ap_authenticator_cksumdata (k5->gt;ap, out, &len);
  if (rc != SHISHI_OK)
    {
      free (out);
      return GSS_S_FAILURE;
    }
  if (memcmp (out, "\x10\x00\x00\x00", 4) != 0)
    {
      free (out);
      return GSS_S_DEFECTIVE_TOKEN;
    }
  if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
    {
      rc = hash_cb (minor_status, context_handle,
		    input_chan_bindings, &md5hash);
      if (rc != GSS_S_COMPLETE)
	{
	  free (out);
	  return GSS_S_DEFECTIVE_TOKEN;
	}
      rc = memcmp (&out[4], md5hash, 16);
      free (md5hash);
    }
  else
    {
      char zeros[16];
      memset (&zeros[0], 0, sizeof zeros);
      rc = memcmp (&out[4], zeros, 16);
    }
  free (out);
  if (rc != 0)
    return GSS_S_DEFECTIVE_TOKEN;
  return GSS_S_COMPLETE;
}
 | 
| ↓ | _gss_decapsulate_token | 11 | 35 | 53 | asn1.c | 
| 
int
_gss_decapsulate_token (const char *in, size_t inlen,
			char **oid, size_t * oidlen,
			char **out, size_t * outlen)
{
  size_t i;
  size_t asn1lenlen;
  if (inlen-- == 0)
    return -1;
  if (*in++ != '\x60')
    return -1;
  i = inlen;
  asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
  if (inlen 
 | 
| ↓ | gss_inquire_saslname_for_mech | 11 | 24 | 47 | saslname.c | 
| 
OM_uint32
gss_inquire_saslname_for_mech (OM_uint32 * minor_status,
			       const gss_OID desired_mech,
			       gss_buffer_t sasl_mech_name,
			       gss_buffer_t mech_name,
			       gss_buffer_t mech_description)
{
  _gss_mech_api_t m;
  if (!desired_mech)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_CALL_INACCESSIBLE_READ;
    }
  m = _gss_find_mech_no_default (desired_mech);
  if (!m)
    {
      if (minor_status)
	*minor_status = 0;
      return GSS_S_BAD_MECH;
    }
  bindtextdomain (PACKAGE PO_SUFFIX, LOCALEDIR);
  if (dup_data (minor_status, sasl_mech_name,
		m->gt;sasl_name, 0) != GSS_S_COMPLETE)
    return GSS_S_FAILURE;
  if (dup_data (minor_status, mech_name, m->gt;mech_name, 0) != GSS_S_COMPLETE)
    {
      if (sasl_mech_name)
	free (sasl_mech_name->gt;value);
      return GSS_S_FAILURE;
    }
  if (dup_data (minor_status, mech_description,
		m->gt;mech_description, 1) != GSS_S_COMPLETE)
    {
      if (sasl_mech_name)
	free (sasl_mech_name->gt;value);
      if (mech_name)
	free (mech_name->gt;value);
      return GSS_S_FAILURE;
    }
  return GSS_S_COMPLETE;
}
 | 
|  | init_request | 10 | 38 | 81 | krb5/context.c | 
|  | hash_cb | 10 | 36 | 61 | krb5/checksum.c | 
|  | gss_acquire_cred | 10 | 27 | 63 | cred.c | 
|  | gss_duplicate_name | 10 | 26 | 42 | name.c | 
|  | inquire_cred | 10 | 21 | 40 | krb5/cred.c | 
|  | gss_accept_sec_context | 9 | 26 | 67 | context.c | 
|  | gss_krb5_acquire_cred | 9 | 25 | 53 | krb5/cred.c | 
|  | gss_krb5_display_status | 9 | 24 | 68 | krb5/error.c | 
|  | gss_delete_sec_context | 8 | 22 | 43 | context.c | 
|  | gss_import_name | 8 | 21 | 37 | name.c | 
|  | gss_release_cred | 8 | 21 | 36 | cred.c | 
|  | gss_inquire_cred_by_mech | 8 | 20 | 51 | cred.c | 
|  | gss_display_name | 8 | 17 | 30 | name.c | 
|  | gss_compare_name | 7 | 9 | 20 | name.c | 
|  | _gss_find_mech_by_saslname | 7 | 9 | 17 | meta.c | 
|  | init_reply | 7 | 24 | 58 | krb5/context.c | 
|  | gss_decapsulate_token | 7 | 21 | 36 | asn1.c | 
|  | _gss_asn1_get_length_der | 7 | 20 | 43 | asn1.c | 
|  | _gss_copy_oid | 7 | 14 | 25 | misc.c | 
|  | _gss_krb5_checksum_pack | 6 | 25 | 124 | krb5/checksum.c | 
|  | _gss_inquire_mechs_for_name3 | 6 | 17 | 30 | name.c | 
|  | gss_export_name | 6 | 16 | 33 | name.c | 
|  | gss_inquire_cred | 6 | 16 | 36 | cred.c | 
|  | gss_inquire_mechs_for_name | 6 | 15 | 30 | name.c | 
|  | _gss_asn1_length_der | 6 | 15 | 32 | asn1.c | 
|  | gss_test_oid_set_member | 6 | 14 | 28 | misc.c | 
|  | gss_inquire_mech_for_saslname | 6 | 13 | 27 | saslname.c | 
|  | gss_inquire_names_for_mech | 5 | 17 | 29 | name.c | 
|  | gss_release_oid_set | 5 | 14 | 20 | misc.c | 
|  | gss_context_time | 5 | 11 | 23 | context.c | 
|  | gss_get_mic | 5 | 11 | 26 | msg.c | 
|  | gss_krb5_delete_sec_context | 5 | 11 | 21 | krb5/context.c | 
|  | gss_unwrap | 5 | 11 | 27 | msg.c | 
|  | dup_data | 5 | 11 | 21 | saslname.c | 
|  | gss_wrap | 5 | 11 | 28 | msg.c | 
|  | gss_encapsulate_token | 5 | 11 | 26 | asn1.c | 
|  | gss_verify_mic | 5 | 11 | 26 | msg.c | 
|  | gss_krb5_context_time | 5 | 10 | 23 | krb5/context.c | 
|  | gss_release_name | 5 | 10 | 20 | name.c | 
|  | _gss_encapsulate_token_prefix | 4 | 25 | 39 | asn1.c | 
|  | gss_krb5_export_name | 4 | 20 | 32 | krb5/name.c | 
|  | _gss_inquire_mechs_for_name1 | 4 | 12 | 22 | name.c | 
|  | _gss_inquire_mechs_for_name2 | 4 | 11 | 22 | name.c | 
|  | gss_indicate_mechs | 4 | 11 | 20 | misc.c | 
|  | _gss_indicate_mechs1 | 4 | 11 | 18 | meta.c | 
|  | gss_create_empty_oid_set | 4 | 10 | 18 | misc.c | 
|  | gss_oid_equal | 4 | 1 | 8 | oid.c | 
|  | gss_krb5_release_cred | 3 | 9 | 16 | krb5/cred.c | 
|  | gss_krb5_tktlifetime | 3 | 8 | 16 | krb5/utils.c | 
|  | _gss_find_mech_no_default | 3 | 7 | 11 | meta.c | 
|  | gss_canonicalize_name | 3 | 7 | 18 | name.c | 
|  | gss_release_buffer | 3 | 7 | 15 | misc.c | 
|  | _gss_find_mech | 3 | 4 | 12 | meta.c | 
|  | gss_check_version | 3 | 3 | 8 | version.c | 
|  | gss_krb5_inquire_cred_by_mech | 2 | 5 | 19 | krb5/cred.c | 
|  | gss_userok | 2 | 1 | 7 | ext.c | 
|  | pack_uint32 | 1 | 4 | 8 | krb5/checksum.c | 
|  | gss_process_context_token | 1 | 1 | 7 | context.c | 
|  | gss_unseal | 1 | 1 | 11 | obsolete.c | 
|  | gss_seal | 1 | 1 | 12 | obsolete.c | 
|  | gss_krb5_verify_mic | 1 | 1 | 8 | krb5/msg.c | 
|  | gss_verify | 1 | 1 | 9 | obsolete.c | 
|  | gss_krb5_get_mic | 1 | 1 | 9 | krb5/msg.c | 
|  | gss_add_cred | 1 | 1 | 14 | cred.c | 
|  | gss_sign | 1 | 1 | 9 | obsolete.c | 
|  | gss_krb5_inquire_cred | 1 | 1 | 11 | krb5/cred.c | 
|  | gss_import_sec_context | 1 | 1 | 7 | context.c | 
|  | gss_export_sec_context | 1 | 1 | 7 | context.c | 
|  | gss_wrap_size_limit | 1 | 1 | 9 | context.c | 
|  | gss_inquire_context | 1 | 1 | 11 | context.c |