Esempio n. 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;
}
Esempio n. 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;
}
Esempio n. 3
0
/* authentication, server side */
int
get_auth (int infd, krb5_context *ctx, krb5_auth_context *actx,
	  krb5_keyblock **key, const char **err_msg,
	  int *protoversion, int *cksumtype,
	  char **cksum, size_t *cksumlen, char *srvname)
{
  char *out;
  size_t outlen;
  char *buf;
  int buflen;
  int len;
  int rc;
  int error;
  /* KERBEROS 5 SENDAUTH MESSAGE */
  char krb5sendauth[] = "KRB5_SENDAUTH_V1.0";
  /* PROTOCOL VERSION */
  char krb5kcmd1[] = "KCMDV0.1";
  char krb5kcmd2[] = "KCMDV0.2";
  char *servername, *server = NULL, *realm = NULL;

  *err_msg = NULL;
  /* Get key for the server. */

# if 0
  /*
   * XXX: Taken straight from the version for libshishi.
   * XXX: No adaptions yet.
   */
  rc = shishi_init_server (handle);
  if (rc != SHISHI_OK)
    return rc;

  if (srvname && *srvname)
    {
      rc = shishi_parse_name (*handle, srvname, &server, &realm);
      if (rc != SHISHI_OK)
	{
	  *err_msg = shishi_strerror (rc);
	  return rc;
	}
    }

  if (server && *server)
    {
      char *p;

      servername = malloc (sizeof (SERVICE) + strlen (server) + 2);
      if (!servername)
	{
	  *err_msg = "Not enough memory";
	  return SHISHI_TOO_SMALL_BUFFER;
	}

      p = strchr (server, '/');
      if (p && (p != server))
	sprintf (servername, "%s", server);	/* Non-empty prefix.  */
      else
	sprintf (servername, "%s/%s", SERVICE,
		 server + (p ? 1 : 0));	/* Remove initial slash.  */
    }
  else
    servername = shishi_server_for_local_service (*handle, SERVICE);

  if (realm && *realm)
    shishi_realm_default_set (*handle, realm);

  free (server);
  free (realm);

  /* Enable use of `~/.k5login'.  */
  if (shishi_check_version ("1.0.2"))	/* Faulty in version 1.0.1.  */
    {
      rc = shishi_cfg_authorizationtype_set (*handle, "k5login basic");
      if (rc != SHISHI_OK)
	{
	  *err_msg = shishi_error (*handle);
	  return rc;
	}
    }

  key = shishi_hostkeys_for_serverrealm (*handle, servername,
					 shishi_realm_default (*handle));
  free (servername);
  if (!key)
    {
      *err_msg = shishi_error (*handle);
      return SHISHI_INVALID_KEY;
    }

  /* Read Kerberos 5 sendauth message */
  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading message size";
      return SHISHI_IO_ERROR;
    }

  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return SHISHI_TOO_SMALL_BUFFER;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading authentication message";
      return SHISHI_IO_ERROR;
    }

  len = strlen (krb5sendauth);
  rc = strncmp (buf, krb5sendauth, buflen >= len ? len : buflen);
  if (rc)
    {
      *err_msg = "Invalid authentication type";
      /* Authentication type is wrong.  */
      write (infd, "\001", 1);
      return SHISHI_VERIFY_FAILED;
    }

  free (buf);

  /* Read protocol version */
  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading protocol message size";
      return SHISHI_IO_ERROR;
    }
  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return SHISHI_TOO_SMALL_BUFFER;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading protocol message";
      return SHISHI_IO_ERROR;
    }

  len = strlen (krb5kcmd1);
  rc = strncmp (buf, krb5kcmd1, buflen >= len ? len : buflen);
  if (rc)
    {
      len = strlen (krb5kcmd2);
      rc = strncmp (buf, krb5kcmd2, buflen >= len ? len : buflen);
      if (rc)
	{
	  *err_msg = "Protocol version not supported";
	  /* Protocol version is wrong.  */
	  write (infd, "\002", 1);
	  return SHISHI_VERIFY_FAILED;
	}
      *protoversion = 2;
    }
  else
    *protoversion = 1;

  free (buf);

  /* Authentication type is ok */

  write (infd, "\0", 1);

  /* Read Authentication request from client */

  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading authentication request size";
      return SHISHI_IO_ERROR;
    }

  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return SHISHI_TOO_SMALL_BUFFER;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading authentication request";
      return SHISHI_IO_ERROR;
    }

  /* Create Authentication context */

  rc = shishi_ap_nosubkey (*handle, ap);
  if (rc != SHISHI_OK)
    return rc;

  /* Store request in context */

  rc = shishi_ap_req_der_set (*ap, buf, buflen);
  if (rc != SHISHI_OK)
    return rc;

  free (buf);

  /* Process authentication request */

  rc = shishi_ap_req_process (*ap, key);
  if (rc != SHISHI_OK)
    return rc;

# ifdef ENCRYPTION

  /* extract subkey if present from ap exchange for secure connection */
  if (*protoversion == 2)
    {
      *enckey = NULL;
      shishi_authenticator_get_subkey (*handle,
				       shishi_ap_authenticator (*ap), enckey);
    }

# endif

  /* Get authenticator checksum */
  rc = shishi_authenticator_cksum (*handle,
				   shishi_ap_authenticator (*ap),
				   cksumtype, cksum, cksumlen);
  if (rc != SHISHI_OK)
    return rc;

  /* User is authenticated.  */
  error = 0;
  write (infd, &error, sizeof (int));

  /* Authenticate ourself to client, if requested.  */

  if (shishi_apreq_mutual_required_p (*handle, shishi_ap_req (*ap)))
    {
      int len;

      rc = shishi_ap_rep_der (*ap, &out, &outlen);
      if (rc != SHISHI_OK)
	return rc;

      len = outlen;
      len = htonl (len);
      rc = write (infd, &len, sizeof (len));
      if (rc != sizeof (int))
	{
	  *err_msg = "Error sending AP-REP";
	  free (out);
	  return SHISHI_IO_ERROR;
	}

      rc = write (infd, out, ntohl (len));
      if (rc != (int) ntohl (len))
	{
	  *err_msg = "Error sending AP-REP";
	  free (out);
	  return SHISHI_IO_ERROR;
	}

      free (out);

      /* We are authenticated to client */
    }

# ifdef ENCRYPTION
  if (*protoversion == 1)
    {
      Shishi_tkt *tkt;

      tkt = shishi_ap_tkt (*ap);
      if (tkt == NULL)
	{
	  *err_msg = "Could not get tkt from AP-REQ";
	  return SHISHI_INVALID_TICKET;
	}

      rc = shishi_encticketpart_get_key (*handle,
					 shishi_tkt_encticketpart (tkt),
					 enckey);
      if (rc != SHISHI_OK)
	return rc;
    }
# endif /* ENCRYPTION */

  return 0;
# else
  return -1;
# endif
}
Esempio n. 4
0
int
get_auth (int infd, Shishi ** handle, Shishi_ap ** ap,
	  Shishi_key ** enckey, const char **err_msg, int *protoversion,
	  int *cksumtype, char **cksum, int *cksumlen)
{
  Shishi_key *key;
  char *out;
  int outlen;
  char *buf;
  int buflen;
  int len;
  int rc;
  int i;
  int error;
  /* KERBEROS 5 SENDAUTH MESSAGE */
  char krb5sendauth[] = "KRB5_SENDAUTH_V1.0";
  /* PROTOCOL VERSION */
  char krb5kcmd1[] = "KCMDV0.1";
  char krb5kcmd2[] = "KCMDV0.2";
  int auth_correct = 0;
  char *servername;

  *err_msg = NULL;
  /* Get key for the server. */

  if (!shishi_check_version (SHISHI_VERSION))
    {
      *err_msg =
	"shishi_check_version() failed: header file incompatible with shared library.";
      return 1;
    }

  rc = shishi_init_server (handle);
  if (rc != SHISHI_OK)
    return rc;

  servername = shishi_server_for_local_service (*handle, SERVICE);

  key = shishi_hostkeys_for_server (*handle, servername);
  if (!key)
    {
      *err_msg = shishi_error (*handle);
      return 1;
    }

  /* Read Kerberos 5 sendauth message */
  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading message size";
      return 1;
    }

  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return 1;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading authentication message";
      return 1;
    }

  len = strlen (krb5sendauth);
  rc = strncmp (buf, krb5sendauth, buflen >= len ? len : buflen);
  if (rc)
    {
      *err_msg = "Invalid authentication type";
      return 1;
    }

  free (buf);

  /* Read protocol version */
  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading protocol message size";
      return 1;
    }
  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return 1;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading protocol message";
      return 1;
    }

  len = strlen (krb5kcmd1);
  rc = strncmp (buf, krb5kcmd1, buflen >= len ? len : buflen);
  if (rc)
    {
      len = strlen (krb5kcmd2);
      rc = strncmp (buf, krb5kcmd2, buflen >= len ? len : buflen);
      if (rc)
	{
	  *err_msg = "Protocol version not supported";
	  return 1;
	}
      *protoversion = 2;
    }
  else
    *protoversion = 1;

  free (buf);

  /* Authentication type is ok */

  write (infd, "\0", 1);

  /* Read Authentication request from client */

  rc = read (infd, &len, sizeof (int));
  if (rc != sizeof (int))
    {
      *err_msg = "Error reading authentication request size";
      return 1;
    }

  buflen = ntohl (len);
  buf = malloc (buflen);
  if (!buf)
    {
      *err_msg = "Not enough memory";
      return 1;
    }

  rc = read (infd, buf, buflen);
  if (rc != buflen)
    {
      *err_msg = "Error reading authentication request";
      return 1;
    }

  /* Create Authentication context */

  rc = shishi_ap_nosubkey (*handle, ap);
  if (rc != SHISHI_OK)
    return rc;

  /* Store request in context */

  shishi_ap_req_der_set (*ap, buf, buflen);
  if (rc != SHISHI_OK)
    return rc;

  free (buf);

  /* Process authentication request */

  rc = shishi_ap_req_process (*ap, key);
  if (rc != SHISHI_OK)
    return rc;

# ifdef ENCRYPTION

  /* extract subkey if present from ap exchange for secure connection */
  if (*protoversion == 2)
    {
      *enckey = NULL;
      shishi_authenticator_get_subkey (*handle,
				       shishi_ap_authenticator (*ap), enckey);
    }

# endif

  /* Get authenticator checksum */
  rc = shishi_authenticator_cksum (*handle,
				   shishi_ap_authenticator (*ap),
				   cksumtype, cksum, cksumlen);
  if (rc != SHISHI_OK)
    return rc;

  /* User is authenticated. */
  error = 0;
  write (infd, &error, sizeof (int));

  /* Authenticate ourself to client, if request */

  if (shishi_apreq_mutual_required_p (*handle, shishi_ap_req (*ap)))
    {
      rc = shishi_ap_rep_der (*ap, &out, &outlen);
      if (rc != SHISHI_OK)
	return rc;

      outlen = htonl (outlen);
      rc = write (infd, &outlen, sizeof (int));
      if (rc != sizeof (int))
	{
	  *err_msg = "Error sending AP-REP";
	  free (out);
	  return 1;
	}

      rc = write (infd, out, ntohl (outlen));
      if (rc != ntohl (outlen))
	{
	  *err_msg = "Error sending AP-REP";
	  free (out);
	  return 1;
	}

      free (out);

      /* We are authenticated to client */
    }

# ifdef ENCRYPTION
  if (*protoversion == 1)
    {
      Shishi_tkt *tkt;

      tkt = shishi_ap_tkt (*ap);
      if (tkt == NULL)
	{
	  *err_msg = "Could not get tkt from AP-REQ";
	  return 1;
	}

      rc = shishi_encticketpart_get_key (*handle,
					 shishi_tkt_encticketpart (tkt),
					 enckey);
      if (rc != SHISHI_OK)
	return rc;
    }
# endif

  return SHISHI_OK;
}