Example #1
0
  /**
   * Updates the signing certificate of a trust bundle.
   *
   * @param bundleName The name of the trust bundle to update.
   * @param certData A DER encoded representation of the new signing certificate.
   * @return Status of 204 if the trust bundle's signing certificate was updated, status of 400 if
   *     the signing certificate is invalid, or a status 404 if a trust bundle with the given name
   *     does not exist.
   */
  @POST
  @Path("{bundle}/signingCert")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response updateSigningCert(@PathParam("bundle") String bundleName, byte[] certData) {
    X509Certificate signingCert = null;
    if (certData.length > 0) {
      try {
        signingCert = CertUtils.toX509Certificate(certData);
      } catch (CertificateConversionException ex) {
        log.error("Signing certificate is not in a valid format " + bundleName, ex);
        return Response.status(Status.BAD_REQUEST).cacheControl(noCache).build();
      }
    }

    // make sure the bundle exists
    org.nhindirect.config.store.TrustBundle entityBundle;
    try {
      entityBundle = bundleDao.getTrustBundleByName(bundleName);
      if (entityBundle == null)
        return Response.status(Status.NOT_FOUND).cacheControl(noCache).build();
    } catch (Exception e) {
      log.error("Error looking up bundle.", e);
      return Response.serverError().cacheControl(noCache).build();
    }

    // now update
    try {
      bundleDao.updateTrustBundleSigningCertificate(entityBundle.getId(), signingCert);

      return Response.noContent().cacheControl(noCache).build();
    } catch (Exception e) {
      log.error("Error updating trust bundle signing certificate.", e);
      return Response.serverError().cacheControl(noCache).build();
    }
  }
Example #2
0
  /**
   * Updates multiple bundle attributes. If the URL of the bundle changes, then the bundle is
   * automatically refreshed.
   *
   * @param bundleName The name of the bundle to update.
   * @param bundleData The data of the trust bundle to update. Empty or null attributes indicate
   *     that the attribute should not be changed.
   * @return Status of 204 if the bundle attributes were updated, status of 400 if the signing
   *     certificate is invalid, or a status 404 if a trust bundle with the given name does not
   *     exist.
   */
  @POST
  @Path("{bundle}/bundleAttributes")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response updateBundleAttributes(
      @PathParam("bundle") String bundleName, TrustBundle bundleData) {
    // make sure the bundle exists
    org.nhindirect.config.store.TrustBundle entityBundle;
    try {
      entityBundle = bundleDao.getTrustBundleByName(bundleName);
      if (entityBundle == null)
        return Response.status(Status.NOT_FOUND).cacheControl(noCache).build();
    } catch (Exception e) {
      log.error("Error looking up bundle.", e);
      return Response.serverError().cacheControl(noCache).build();
    }

    final String oldBundleURL = entityBundle.getBundleURL();

    // if there is a signing certificate in the request, make sure it's valid
    X509Certificate newSigningCert = null;
    if (bundleData.getSigningCertificateData() != null) {

      try {
        newSigningCert = CertUtils.toX509Certificate(bundleData.getSigningCertificateData());
      } catch (CertificateConversionException ex) {
        log.error("Signing certificate is not in a valid format " + bundleName, ex);
        return Response.status(Status.BAD_REQUEST).cacheControl(noCache).build();
      }
    }

    // update the bundle
    try {
      bundleDao.updateTrustBundleAttributes(
          entityBundle.getId(),
          bundleData.getBundleName(),
          bundleData.getBundleURL(),
          newSigningCert,
          bundleData.getRefreshInterval());

      // if the URL changed, the bundle needs to be refreshed
      if (bundleData.getBundleURL() != null
          && !bundleData.getBundleURL().isEmpty()
          && !oldBundleURL.equals(bundleData.getBundleURL())) {
        entityBundle = bundleDao.getTrustBundleById(entityBundle.getId());

        template.sendBody(entityBundle);
      }

      return Response.noContent().cacheControl(noCache).build();
    } catch (Exception e) {
      log.error("Error updating trust bundle attributes.", e);
      return Response.serverError().cacheControl(noCache).build();
    }
  }
  private X509Certificate certFromData(byte[] data) {
    X509Certificate retVal = null;
    try {
      // first check for wrapped data
      final CertContainer container = CertUtils.toCertContainer(data);
      if (container.getWrappedKeyData() != null) {
        // this is a wrapped key
        // make sure we have a KeyStoreManager configured
        if (this.mgr == null) {
          throw new NHINDException(
              AgentError.Unexpected,
              "Resolved certifiate has wrapped data, but resolver has not been configured to unwrap it.");
        }

        // create a new wrapped certificate object
        retVal =
            WrappedOnDemandX509CertificateEx.fromX509Certificate(
                mgr, container.getCert(), container.getWrappedKeyData());
        return retVal;
      }

      ByteArrayInputStream bais = new ByteArrayInputStream(data);

      // lets try this a as a PKCS12 data stream first
      try {
        KeyStore localKeyStore =
            KeyStore.getInstance("PKCS12", CryptoExtensions.getJCEProviderName());

        localKeyStore.load(bais, "".toCharArray());
        Enumeration<String> aliases = localKeyStore.aliases();

        // we are really expecting only one alias
        if (aliases.hasMoreElements()) {
          String alias = aliases.nextElement();
          X509Certificate cert = (X509Certificate) localKeyStore.getCertificate(alias);

          // check if there is private key
          Key key = localKeyStore.getKey(alias, "".toCharArray());
          if (key != null && key instanceof PrivateKey) {
            retVal = X509CertificateEx.fromX509Certificate(cert, (PrivateKey) key);
          } else retVal = cert;
        }
      } catch (Exception e) {
        // must not be a PKCS12 stream, go on to next step
      }

      if (retVal == null) {
        // try X509 certificate factory next
        bais.reset();
        bais = new ByteArrayInputStream(data);

        retVal =
            (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(bais);
      }
      bais.close();
    } catch (Exception e) {
      throw new NHINDException("Data cannot be converted to a valid X.509 Certificate", e);
    }

    return retVal;
  }
Example #4
0
  /**
   * Processes all DNS CERT requests.
   *
   * @param name The record name. In many cases this a email address.
   * @return Returns a set of record responses to the request.
   * @throws DNSException
   */
  @SuppressWarnings("unused")
  protected RRset processCERTRecordRequest(String name) throws DNSException {
    if (name.endsWith(".")) name = name.substring(0, name.length() - 1);

    Certificate[] certs;

    // use the certificate configuration service
    try {
      certs = proxy.getCertificatesForOwner(name, null);
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "DNS service proxy call for certificates failed: " + e.getMessage(),
          e);
    }

    if (certs == null || certs.length == 0) {
      // unless the call above was for an org level cert, it will probably always fail because the
      // "name" parameter has had all instances of "@" replaced with ".".  The certificate service
      // stores owners using "@".
      // This is horrible, but try hitting the cert service replacing each "." with "@" one by one.
      // Start at the beginning of the address because this is more than likely where the "@"
      // character
      // will be.
      int previousIndex = 0;
      int replaceIndex = 0;
      while ((replaceIndex = name.indexOf(".", previousIndex)) > -1) {
        char[] chars = name.toCharArray();
        chars[replaceIndex] = '@';
        try {
          certs = proxy.getCertificatesForOwner(String.copyValueOf(chars), null);
        } catch (Exception e) {
          throw new DNSException(
              DNSError.newError(Rcode.SERVFAIL),
              "DNS service proxy call for certificates failed: " + e.getMessage(),
              e);
        }
        if (certs != null && certs.length > 0) break;

        if (replaceIndex >= (name.length() - 1)) break;

        previousIndex = replaceIndex + 1;
      }
    }

    if (certs == null || certs.length == 0) return null;

    if (!name.endsWith(".")) name += ".";

    RRset retVal = new RRset();
    try {
      for (Certificate cert : certs) {
        int certRecordType = CERTRecord.PKIX;
        byte[] retData = null;

        X509Certificate xCert = null;
        try {
          // need to convert to cert container because this might be
          // a certificate with wrapped private key data
          final CertUtils.CertContainer cont = CertUtils.toCertContainer(cert.getData());
          xCert = cont.getCert();
          // check if this is a compliant certificate with the configured policy... if not, move on
          if (!isCertCompliantWithPolicy(xCert)) continue;

          retData = xCert.getEncoded();
        } catch (CertificateConversionException e) {
          // probably not a Certificate... might be a URL
        }

        if (xCert == null) {
          // see if it's a URL
          try {
            retData = cert.getData();
            URL url = new URL(new String(retData));
            certRecordType = CERTRecord.URI;
          } catch (Exception e) {
            throw new DNSException(
                DNSError.newError(Rcode.SERVFAIL),
                "Failure while parsing CERT record data: " + e.getMessage(),
                e);
          }
        }

        int keyTag = 0;
        int alg = 0;
        if (xCert != null && xCert.getPublicKey() instanceof RSAKey) {
          RSAKey key = (RSAKey) xCert.getPublicKey();
          byte[] modulus = key.getModulus().toByteArray();

          keyTag = (modulus[modulus.length - 2] << 8) & 0xFF00;

          keyTag |= modulus[modulus.length - 1] & 0xFF;
          alg = 5;
        }

        CERTRecord rec =
            new CERTRecord(
                Name.fromString(name),
                DClass.IN,
                86400L,
                certRecordType,
                keyTag,
                alg /*public key alg, RFC 4034*/,
                retData);

        retVal.addRR(rec);
      }
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "Failure while parsing CERT record data: " + e.getMessage(),
          e);
    }

    // because of policy filtering, it's possible that we could have filtered out every cert
    // resulting in an empty RR set
    return (retVal.size() == 0) ? null : retVal;
  }