@Override
  public Component preview() {
    final Label commonNameLabel = new Label("certCommonName", new Model<String>());
    final ByteArrayInputStream certificateStream = new ByteArrayInputStream(uploadedBytes);
    try {
      final X509Certificate certificate =
          (X509Certificate)
              CertificateFactory.getInstance("X.509").generateCertificate(certificateStream);

      final StringBuilder commonNameBuilder = new StringBuilder("cn=");

      final LdapName ldapName = new LdapName(certificate.getIssuerDN().getName());

      for (Rdn rdn : ldapName.getRdns()) {
        if ("CN".equalsIgnoreCase(rdn.getType())) {
          commonNameBuilder.append(
              rdn.getValue() == null ? StringUtils.EMPTY : rdn.getValue().toString());
        }
      }
      commonNameLabel.setDefaultModelObject(commonNameBuilder.toString());
    } catch (Exception e) {
      LOG.error("Error evaluating certificate file", e);
      throw new IllegalArgumentException("Error evaluating certificate file", e);
    } finally {
      IOUtils.closeQuietly(certificateStream);
    }
    return this.add(commonNameLabel);
  }
 /**
  * Seeds the bound instance's local ads-truststore with a set of instance key-pair public key
  * certificates. The result is the instance will trust any instance posessing the private key
  * corresponding to one of the public-key certificates. This trust is necessary at least to
  * initialize replication, which uses the trusted certificate entries in the ads-truststore for
  * server authentication.
  *
  * @param ctx The bound instance.
  * @param keyEntryMap The set of valid (i.e., not tagged as compromised) instance key-pair
  *     public-key certificate entries in ADS represented as a map from keyID to public-key
  *     certificate (binary).
  * @throws NamingException in case an error occurs while updating the instance's ads-truststore
  *     via LDAP.
  */
 public static void seedAdsTrustStore(InitialLdapContext ctx, Map<String, byte[]> keyEntryMap)
     throws NamingException {
   /* TODO: this DN is declared in some core constants file. Create a
   constants file for the installer and import it into the core. */
   final Attribute oc = new BasicAttribute("objectclass");
   oc.add("top");
   oc.add("ds-cfg-instance-key");
   for (Map.Entry<String, byte[]> keyEntry : keyEntryMap.entrySet()) {
     final BasicAttributes keyAttrs = new BasicAttributes();
     keyAttrs.put(oc);
     final Attribute rdnAttr =
         new BasicAttribute(
             ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyEntry.getKey());
     keyAttrs.put(rdnAttr);
     keyAttrs.put(
         new BasicAttribute(
             ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName()
                 + ";binary",
             keyEntry.getValue()));
     final LdapName keyDn =
         new LdapName(
             (new StringBuilder(rdnAttr.getID()))
                 .append("=")
                 .append(Rdn.escapeValue(rdnAttr.get()))
                 .append(",")
                 .append(TRUSTSTORE_DN)
                 .toString());
     try {
       ctx.createSubcontext(keyDn, keyAttrs).close();
     } catch (NameAlreadyBoundException x) {
       ctx.destroySubcontext(keyDn);
       ctx.createSubcontext(keyDn, keyAttrs).close();
     }
   }
 }
Beispiel #3
0
 /**
  * Compares the specified Object with this Rdn for equality. Returns true if the given object is
  * also a Rdn and the two Rdns represent the same attribute type and value mappings. The order of
  * components in multi-valued Rdns (such as "ou=Sales+cn=Bob") is not significant.
  *
  * <p>Type and value equality matching is done as below:
  *
  * <ul>
  *   <li>The types are compared for equality with their case ignored.
  *   <li>String values with different but equivalent usage of quoting, escaping, or
  *       UTF8-hex-encoding are considered equal. The case of the values is ignored during the
  *       comparison.
  * </ul>
  *
  * <p>If obj is null or not an instance of Rdn, false is returned.
  *
  * <p>
  *
  * @param obj object to be compared for equality with this Rdn.
  * @return true if the specified object is equal to this Rdn.
  * @see #hashCode()
  */
 public boolean equals(Object obj) {
   if (obj == this) {
     return true;
   }
   if (!(obj instanceof Rdn)) {
     return false;
   }
   Rdn that = (Rdn) obj;
   if (entries.size() != that.size()) {
     return false;
   }
   for (int i = 0; i < entries.size(); i++) {
     if (!entries.get(i).equals(that.entries.get(i))) {
       return false;
     }
   }
   return true;
 }
  private String getIssuer(X509Certificate certificate) {
    try {
      StringBuilder builder = new StringBuilder();
      LdapName ldapDN = new LdapName(certificate.getSubjectX500Principal().getName());
      for (Rdn rdn : ldapDN.getRdns()) {
        String type = getTypeFullName(rdn.getType());
        if (StringUtils.isEmpty(type)) {
          builder
              .append("Serial Number: ")
              .append(toHexString(rdn.getValue().toString().getBytes()));
        } else {
          builder.append(type).append(": ").append(rdn.getValue()).append('\n');
        }
      }

      return builder.toString();
    } catch (InvalidNameException e) {
      return "<Could not determine certificate issuer>";
    }
  }
  /**
   * Construct a "simplified name" based on the subject DN from the certificate. The purpose is to
   * have something shorter to display in the list. The name used is one of the following DN parts,
   * if available, otherwise the complete DN: 'CN', 'OU' or else 'O'.
   *
   * @param cert to read subject DN from
   * @return the simplified name
   */
  private static String getSimplifiedName(X509Certificate cert) {
    final HashMap<String, String> parts = new HashMap<String, String>();
    try {
      for (Rdn name : new LdapName(cert.getSubjectX500Principal().getName()).getRdns()) {
        if (name.getType() != null && name.getValue() != null) {
          parts.put(name.getType(), name.getValue().toString());
        }
      }
    } catch (InvalidNameException ignored) // NOPMD
    {
    }

    String result = parts.get("CN");
    if (result == null) {
      result = parts.get("OU");
    }
    if (result == null) {
      result = parts.get("O");
    }
    if (result == null) {
      result = cert.getSubjectX500Principal().getName();
    }
    return result;
  }
  private Set<GroupReference> suggestLdap(String name) {
    if (name.isEmpty()) {
      return Collections.emptySet();
    }

    Set<GroupReference> out = Sets.newTreeSet(GROUP_REF_NAME_COMPARATOR);
    try {
      DirContext ctx = helper.open();
      try {
        // Do exact lookups until there are at least 3 characters.
        name = Rdn.escapeValue(name) + ((name.length() >= 3) ? "*" : "");
        LdapSchema schema = helper.getSchema(ctx);
        ParameterizedString filter =
            ParameterizedString.asis(schema.groupPattern.replace(GROUPNAME, name).toString());
        Set<String> returnAttrs = new HashSet<String>(schema.groupName.getParameterNames());
        Map<String, String> params = Collections.emptyMap();
        for (String groupBase : schema.groupBases) {
          LdapQuery query = new LdapQuery(groupBase, schema.groupScope, filter, returnAttrs);
          for (LdapQuery.Result res : query.query(ctx, params)) {
            out.add(groupReference(schema.groupName, res));
          }
        }
      } finally {
        try {
          ctx.close();
        } catch (NamingException e) {
          log.warn("Cannot close LDAP query handle", e);
        }
      }
    } catch (NamingException e) {
      log.warn("Cannot query LDAP for groups matching requested name", e);
    } catch (LoginException e) {
      log.warn("Cannot query LDAP for groups matching requested name", e);
    }
    return out;
  }
  private Object convertSingleValue(
      Column modelElement, String modelAttrName, Class<?> modelAttrClass, Object objResult)
      throws TranslatorException, InvalidNameException {
    if (objResult == null) {
      return null;
    }
    // GHH 20080326 - if attribute is not a string or empty, just
    // return null.
    if (!(objResult instanceof String)) {
      return objResult;
    }

    String strResult = (String) objResult;
    // MPW - 3.9.07 - Also return NULL when attribute is unset or empty string.
    // There is no way to differentiate between being unset and being the empty string.
    if (strResult.equals("")) { // $NON-NLS-1$
      return null;
    }

    // MPW: 3-11-07: Added support for java.lang.Integer conversion.
    if (TypeFacility.RUNTIME_TYPES.TIMESTAMP.equals(modelAttrClass)) {
      String timestampFormat = modelElement.getFormat();
      if (timestampFormat == null) {
        timestampFormat = LDAPConnectorConstants.ldapTimestampFormat;
      }
      SimpleDateFormat dateFormat = new SimpleDateFormat(timestampFormat);
      try {
        Date dateResult = dateFormat.parse(strResult);
        Timestamp tsResult = new Timestamp(dateResult.getTime());
        return tsResult;
      } catch (ParseException pe) {
        throw new TranslatorException(
            pe,
            LDAPPlugin.Util.getString(
                "LDAPSyncQueryExecution.timestampParseFailed", modelAttrName)); // $NON-NLS-1$
      }

      //	TODO: Extend support for more types in the future.
      // Specifically, add support for byte arrays, since that's actually supported
      // in the underlying data source.
    }

    // extract rdn
    String type = modelElement.getProperty(LDAPExecutionFactory.RDN_TYPE, false);
    if (type != null) {
      String prefix = modelElement.getProperty(LDAPExecutionFactory.DN_PREFIX, false);
      LdapName name = new LdapName(strResult);
      if (prefix != null) {
        if (!name.getPrefix(name.size() - 1).toString().equals(prefix)) {
          throw new InvalidNameException();
        }
      } else if (name.size() > 1) {
        throw new InvalidNameException();
      }
      Rdn rdn = name.getRdn(name.size() - 1);
      if (!rdn.getType().equals(type)) {
        throw new InvalidNameException();
      }
      return rdn.getValue();
    }

    return strResult; // the Teiid type conversion logic will handle refine from here if necessary
  }
  @Before
  public void before() throws Exception {
    secureRandom = mock(SecureRandom.class);
    whenNew(SecureRandom.class).withNoArguments().thenReturn(secureRandom);

    encoder = mock(Base64.Encoder.class);
    when(encoder.withoutPadding()).thenReturn(encoder);

    when(encoder.encodeToString(any(byte[].class))).thenReturn("password");

    mockStatic(Base64.class);
    when(Base64.getEncoder()).thenReturn(encoder);

    PropertiesGenerator propertiesGenerator = mock(PropertiesGenerator.class);
    when(propertiesGenerator.getProperty(KeyStoreHelper.KEYPASS_PROPERTY, "password"))
        .thenReturn("password");

    whenNew(PropertiesGenerator.class)
        .withArguments("/opt/traffic_router/conf/keystore.properties")
        .thenReturn(propertiesGenerator);

    KeyStoreLoader keyStoreLoader = mock(KeyStoreLoader.class);
    whenNew(KeyStoreLoader.class)
        .withArguments("/opt/traffic_router/db/.keystore", "password".toCharArray())
        .thenReturn(keyStoreLoader);

    keyStore = PowerMockito.mock(KeyStore.class);
    when(keyStoreLoader.load()).thenReturn(keyStore);

    mockStatic(Paths.class);

    Path keystorePath = mock(Path.class);
    when(Paths.get("/opt/traffic_router/db/.keystore")).thenReturn(keystorePath);

    outputStream = mock(OutputStream.class);

    mockStatic(Files.class);
    when(Files.newOutputStream(keystorePath)).thenReturn(outputStream);

    CertAndKeyGen certAndKeyGen = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
    certAndKeyGen.generate(2048);
    privateKey = certAndKeyGen.getPrivateKey();
    x509Certificate =
        certAndKeyGen.getSelfCertificate(
            new X500Name("CN=*.deliveryservice.cdn.example.com"), 600L);

    Rdn rdn = mock(Rdn.class);
    when(rdn.getType()).thenReturn("CN");
    when(rdn.getValue()).thenReturn("*.deliveryservice1.cdn.example.com");

    List<Rdn> rdnList = new ArrayList<>();
    rdnList.add(rdn);

    LdapName ldapName = mock(LdapName.class);
    when(ldapName.getRdns()).thenReturn(rdnList);

    whenNew(LdapName.class)
        .withArguments(
            "CN=*.deliveryservice1.cdn.example.com,OU=Traffic Routing,O=Traffic Control CDN,C=US")
        .thenReturn(ldapName);

    X509Certificate x509Certificate = PowerMockito.mock(X509Certificate.class);
    X500Principal x500Principal =
        new X500Principal(
            "CN=*.deliveryservice1.cdn.example.com, OU=Traffic Routing, O=Traffic Control CDN, C=US");

    when(x509Certificate.getSubjectX500Principal()).thenReturn(x500Principal);

    PowerMockito.when(keyStore.aliases())
        .thenAnswer(
            invocation -> {
              Vector<String> vector = new Vector<>();
              vector.add("alias-1");
              vector.add("alias-2");
              return vector.elements();
            });

    PowerMockito.when(keyStore.getCertificate("alias-1")).thenReturn(x509Certificate);
    PowerMockito.when(keyStore.getCertificate("alias-2")).thenReturn(mock(Certificate.class));
  }
Beispiel #9
0
  /**
   * Register instance key-pair public-key certificate provided in serverProperties: generate a
   * key-id attribute if one is not provided (as expected); add an instance key public-key
   * certificate entry for the key certificate; and associate the certificate entry with the server
   * entry via the key ID attribute.
   *
   * @param ctx the InitialLdapContext on the server we want to update.
   * @param serverProperties Properties of the server being registered to which the instance key
   *     entry belongs.
   * @param serverEntryDn The server's ADS entry DN.
   * @throws ADSContextException In case some JNDI operation fails or there is a problem getting the
   *     instance public key certificate ID.
   */
  void registerInstanceKeyCertificate(
      InitialLdapContext ctx, Map<ServerProperty, Object> serverProperties, LdapName serverEntryDn)
      throws ADSContextException {
    assert serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE);
    if (!serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) {
      return;
    }

    // the key ID might be supplied in serverProperties (although, I am unaware of any such case).
    String keyID = (String) serverProperties.get(ServerProperty.INSTANCE_KEY_ID);

    /* these attributes are used both to search for an existing certificate
    entry and, if one does not exist, add a new certificate entry */
    final BasicAttributes keyAttrs = new BasicAttributes();
    final Attribute oc = new BasicAttribute("objectclass");
    oc.add("top");
    oc.add("ds-cfg-instance-key");
    keyAttrs.put(oc);
    if (null != keyID) {
      keyAttrs.put(new BasicAttribute(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
    }
    keyAttrs.put(
        new BasicAttribute(
            ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary",
            serverProperties.get(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)));

    /* search for public-key certificate entry in ADS DIT */
    final String attrIDs[] = {"ds-cfg-key-id"};
    NamingEnumeration<SearchResult> results = null;
    try {
      results = ctx.search(ADSContext.getInstanceKeysContainerDN(), keyAttrs, attrIDs);
      boolean found = false;
      while (results.hasMore()) {
        final Attribute keyIdAttr = results.next().getAttributes().get(attrIDs[0]);
        if (null != keyIdAttr) {
          /* attribute ds-cfg-key-id is the entry is a MUST in the schema */
          keyID = (String) keyIdAttr.get();
        }
        found = true;
      }
      /* TODO: It is possible (but unexpected) that the caller specifies a
      ds-cfg-key-id value for which there is a certificate entry in ADS, but
      the certificate value does not match that supplied by the caller. The
      above search would not return the entry, but the below attempt to add
      an new entry with the supplied ds-cfg-key-id will fail (throw a
      NameAlreadyBoundException) */
      if (!found) {
        /* create key ID, if it was not supplied in serverProperties */
        if (null == keyID) {
          keyID =
              CryptoManagerImpl.getInstanceKeyID(
                  (byte[]) serverProperties.get(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE));
          keyAttrs.put(
              new BasicAttribute(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
        }

        /* add public-key certificate entry */
        final LdapName keyDn =
            new LdapName(
                ServerProperty.INSTANCE_KEY_ID.getAttributeName()
                    + "="
                    + Rdn.escapeValue(keyID)
                    + ","
                    + ADSContext.getInstanceKeysContainerDN());
        ctx.createSubcontext(keyDn, keyAttrs).close();
      }

      if (serverEntryDn != null) {
        /* associate server entry with certificate entry via key ID attribute */
        ctx.modifyAttributes(
            serverEntryDn,
            InitialLdapContext.REPLACE_ATTRIBUTE,
            new BasicAttributes(ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
      }
    } catch (NamingException | CryptoManagerException ne) {
      throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, ne);
    } finally {
      handleCloseNamingEnumeration(results);
    }
  }
  /**
   * Appends an HTML representation of the given X509Certificate.
   *
   * @param sb StringBuilder to append to
   * @param certificate to print
   */
  private void renderX509(StringBuilder sb, X509Certificate certificate) {
    X500Principal issuer = certificate.getIssuerX500Principal();
    X500Principal subject = certificate.getSubjectX500Principal();

    sb.append("<table cellspacing='1' cellpadding='1'>\n");

    // subject
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_TO"));
    try {
      for (Rdn name : new LdapName(subject.getName()).getRdns()) {
        String nameType = name.getType();
        String lblKey = "service.gui.CERT_INFO_" + nameType;
        String lbl = R.getI18NString(lblKey);

        if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) lbl = nameType;

        final String value;
        Object nameValue = name.getValue();

        if (nameValue instanceof byte[]) {
          byte[] nameValueAsByteArray = (byte[]) nameValue;

          value = getHex(nameValueAsByteArray) + " (" + new String(nameValueAsByteArray) + ")";
        } else value = nameValue.toString();

        addField(sb, lbl, value);
      }
    } catch (InvalidNameException ine) {
      addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), subject.getName());
    }

    // issuer
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_BY"));
    try {
      for (Rdn name : new LdapName(issuer.getName()).getRdns()) {
        String nameType = name.getType();
        String lblKey = "service.gui.CERT_INFO_" + nameType;
        String lbl = R.getI18NString(lblKey);

        if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) lbl = nameType;

        final String value;
        Object nameValue = name.getValue();

        if (nameValue instanceof byte[]) {
          byte[] nameValueAsByteArray = (byte[]) nameValue;

          value = getHex(nameValueAsByteArray) + " (" + new String(nameValueAsByteArray) + ")";
        } else value = nameValue.toString();

        addField(sb, lbl, value);
      }
    } catch (InvalidNameException ine) {
      addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), issuer.getName());
    }

    // validity
    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_VALIDITY"));
    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_ISSUED_ON"),
        certificate.getNotBefore().toString());
    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_EXPIRES_ON"),
        certificate.getNotAfter().toString());

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_FINGERPRINTS"));
    try {
      String sha1String = getThumbprint(certificate, "SHA1");
      String md5String = getThumbprint(certificate, "MD5");

      addField(sb, "SHA1:", sha1String);
      addField(sb, "MD5:", md5String);
    } catch (CertificateException e) {
      // do nothing as we cannot show this value
    }

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_CERT_DETAILS"));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SER_NUM"),
        certificate.getSerialNumber().toString());

    addField(
        sb, R.getI18NString("service.gui.CERT_INFO_VER"), String.valueOf(certificate.getVersion()));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SIGN_ALG"),
        String.valueOf(certificate.getSigAlgName()));

    addTitle(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY_INFO"));

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_ALG"),
        certificate.getPublicKey().getAlgorithm());

    if (certificate.getPublicKey().getAlgorithm().equals("RSA")) {
      RSAPublicKey key = (RSAPublicKey) certificate.getPublicKey();

      addField(
          sb,
          R.getI18NString("service.gui.CERT_INFO_PUB_KEY"),
          R.getI18NString(
              "service.gui.CERT_INFO_KEY_BYTES_PRINT",
              new String[] {
                String.valueOf(key.getModulus().toByteArray().length - 1),
                key.getModulus().toString(16)
              }));

      addField(
          sb, R.getI18NString("service.gui.CERT_INFO_EXP"), key.getPublicExponent().toString());

      addField(
          sb,
          R.getI18NString("service.gui.CERT_INFO_KEY_SIZE"),
          R.getI18NString(
              "service.gui.CERT_INFO_KEY_BITS_PRINT",
              new String[] {String.valueOf(key.getModulus().bitLength())}));
    } else if (certificate.getPublicKey().getAlgorithm().equals("DSA")) {
      DSAPublicKey key = (DSAPublicKey) certificate.getPublicKey();

      addField(sb, "Y:", key.getY().toString(16));
    }

    addField(
        sb,
        R.getI18NString("service.gui.CERT_INFO_SIGN"),
        R.getI18NString(
            "service.gui.CERT_INFO_KEY_BYTES_PRINT",
            new String[] {
              String.valueOf(certificate.getSignature().length), getHex(certificate.getSignature())
            }));

    sb.append("</table>\n");
  }