Exemple #1
0
/* Allows a remotely initiated security context between the
   application and a remote peer to be established, using krb5.
   Assumes context_handle is valid. */
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 data;
    char *in;
    size_t inlen;
    gss_ctx_id_t cx;
    _gss_krb5_ctx_t cxk5;
    _gss_krb5_cred_t crk5;
    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->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->mech = GSS_KRB5;
    cx->krb5 = cxk5;
    /* XXX cx->peer?? */
    *context_handle = cx;

    cxk5->sh = crk5->sh;
    cxk5->key = crk5->key;
    cxk5->acceptor = 1;

    rc = shishi_ap (cxk5->sh, &cxk5->ap);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = gss_decapsulate_token (input_token_buffer, GSS_KRB5, &in, &inlen);
    if (!rc)
        return GSS_S_BAD_MIC;

    if (inlen < TOK_LEN)
        return GSS_S_BAD_MIC;

    if (memcmp (in, TOK_AP_REQ, TOK_LEN) != 0)
        return GSS_S_BAD_MIC;

    rc = shishi_ap_req_der_set (cxk5->ap, in + TOK_LEN, inlen - TOK_LEN);
    if (rc != SHISHI_OK)
        return GSS_S_FAILURE;

    rc = shishi_ap_req_process (cxk5->ap, crk5->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->sh,
            shishi_ap_authenticator (cxk5->ap),
            &cxk5->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->tkt = shishi_ap_tkt (cxk5->ap);
    cxk5->key = shishi_ap_key (cxk5->ap);

    if (shishi_apreq_mutual_required_p (crk5->sh, shishi_ap_req (cxk5->ap)))
    {
        Shishi_asn1 aprep;

        rc = shishi_ap_rep_asn1 (cxk5->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->sh,
                                                shishi_ap_encapreppart (cxk5->
                                                        ap),
                                                &cxk5->acceptseqnr);
        if (rc != SHISHI_OK)
        {
            /* A strict 1964 implementation would return
               GSS_S_DEFECTIVE_TOKEN here.  gssapi-cfx permit absent
               sequence number, though. */
            cxk5->acceptseqnr = 0;
        }

        {
            char *der;
            size_t len;

            rc = shishi_asn1_to_der (crk5->sh, aprep, &der, &len);
            if (rc != SHISHI_OK)
            {
                printf ("Error der encoding aprep: %s\n", shishi_strerror (rc));
                return GSS_S_FAILURE;
            }
            data.value = der;
            data.length = len;
        }

        rc = gss_encapsulate_token_prefix (&data, TOK_AP_REP, TOK_LEN,
                                           GSS_KRB5, output_token);
        if (!rc)
            return GSS_S_FAILURE;

        if (ret_flags)
            *ret_flags = GSS_C_MUTUAL_FLAG;
    }
    else
    {
        output_token->value = NULL;
        output_token->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->sh,
                                          shishi_tkt_encticketpart (cxk5->tkt),
                                          &p->value, &p->length);
        if (rc != SHISHI_OK)
            return GSS_S_FAILURE;

        p->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;
}
Exemple #2
0
static Shishi_ap *
auth (Shishi * h, int verbose, const char *cname, const char *sname)
{
  Shishi_key *key;
  Shishi_ap *ap;
  Shishi_asn1 apreq;
  char *buf;
  size_t buflen;
  int rc;

  printf ("Client: %s\n", cname);
  printf ("Server: %s\n", sname);

  /* Get key for the server. */

  key = shishi_hostkeys_for_server (h, sname);
  if (!key)
    {
      printf ("could not find key: %s\n", shishi_error (h));
      return NULL;
    }

  if (verbose)
    shishi_key_print (h, stderr, key);

  /* Read Authentication request from client */

  printf ("Waiting for client to authenticate itself...\n");

  rc = shishi_apreq_parse (h, stdin, &apreq);
  if (rc != SHISHI_OK)
    {
      printf ("could not read AP-REQ: %s\n", shishi_strerror (rc));
      return NULL;
    }

  /* Create Authentication context */

  rc = shishi_ap (h, &ap);
  if (rc != SHISHI_OK)
    {
      printf ("Could not create AP: %s\n", shishi_strerror (rc));
      return NULL;
    }

  /* Store request in context */

  shishi_ap_req_set (ap, apreq);

  /* Process authentication request */

  rc = shishi_ap_req_process (ap, key);
  if (rc != SHISHI_OK)
    {
      printf ("Could not process AP-REQ: %s\n", shishi_strerror (rc));
      return NULL;
    }

  if (verbose)
    shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap));

  rc = shishi_authenticator_client (h, shishi_ap_authenticator (ap),
				    &buf, &buflen);
  printf ("Client name (from authenticator): %.*s\n", (int) buflen, buf);
  free (buf);

  rc = shishi_encticketpart_clientrealm
    (h, shishi_tkt_encticketpart (shishi_ap_tkt (ap)), &buf, &buflen);
  printf ("Client name (from encticketpart): %.*s\n", (int) buflen, buf);
  free (buf);

  rc = shishi_ticket_server (h, shishi_tkt_ticket (shishi_ap_tkt (ap)),
			     &buf, &buflen);
  printf ("Server name (from ticket): %.*s\n", (int) buflen, buf);
  free (buf);

  /* User is authenticated. */

  printf ("User authenticated.\n");

  /* Authenticate ourself to client, if request */

  if (shishi_apreq_mutual_required_p (h, apreq))
    {
      Shishi_asn1 aprep;

      printf ("Mutual authentication required.\n");

      rc = shishi_ap_rep_asn1 (ap, &aprep);
      if (rc != SHISHI_OK)
	{
	  printf ("Error creating AP-REP: %s\n", shishi_strerror (rc));
	  return NULL;
	}

      if (verbose)
	shishi_encapreppart_print (h, stderr, shishi_ap_encapreppart (ap));

      shishi_aprep_print (h, stdout, aprep);

      /* We are authenticated to client */
    }

  return ap;
}