Skip to content

Commit

Permalink
Merge pull request payara#4042 from Pandrex247/PAYARA-3789-Unify-DN-R…
Browse files Browse the repository at this point in the history
…epresentation

PAYARA-3789 Unify DN Representation
  • Loading branch information
Pandrex247 committed Jun 17, 2019
1 parent 69ced27 commit f8f2450
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@
import java.util.Arrays;

import com.sun.enterprise.security.SecurityContextProxy;
import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
import org.glassfish.security.common.PrincipalImpl;
import com.sun.enterprise.security.SecurityContext;

import javax.security.auth.x500.X500Principal;

public class WebPrincipal extends PrincipalImpl implements SecurityContextProxy {

private static final long serialVersionUID = 1L;
Expand Down Expand Up @@ -83,8 +86,12 @@ public WebPrincipal(String user, char[] pwd, SecurityContext context) {
}

public WebPrincipal(X509Certificate[] certs, SecurityContext context) {
super(certs[0].getSubjectDN().getName());
this.certs = certs;
this(certs, context, false);
}

public WebPrincipal(X509Certificate[] certificates, SecurityContext context, boolean nameFromContext) {
super(getPrincipalName(certificates, context, nameFromContext));
this.certs = certificates;
this.useCertificate = true;
this.securityContext = context;
}
Expand Down Expand Up @@ -146,5 +153,29 @@ public String toString() {
public Principal getCustomPrincipal() {
return customPrincipal;
}

private static String getPrincipalName(X509Certificate[] certificates, SecurityContext context, boolean nameFromContext) {
if (nameFromContext) {
// Use the principal name from the security context, ensuring the context caller principal and
// the web principal have the same name.
//
// This will typically be an org.glassfish.security.common.PrincipalImpl which as its name has
// the name obtained from javax.security.auth.x500.X500Principal, which is obtained from
// certificates[0].getSubjectX500Principal().
//
// I.e. the internal principal in the security context is effectively created via:
//
// new PrincipalImpl(certificates[0].getSubjectX500Principal());
//
// The format of the X.500 distinguished name (DN) returned here will then be RFC 2253, e.g.
// C=UK,ST=lak,L=zak,O=kaz,OU=bar,CN=lfoo
return context.getCallerPrincipal().getName();
}

// Use the full DN name from the certificates. This should normally be the same as
// context.getCallerPrincipal(), but a realm could have decided to map the name in which
// case they will be different.
return certificates[0].getSubjectX500Principal().getName(X500Principal.RFC2253, CertificateRealm.OID_MAP);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@

import javax.security.auth.Subject;

import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
import org.glassfish.enterprise.iiop.api.GlassFishORBHelper;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
Expand Down Expand Up @@ -342,7 +343,8 @@ private void createIdCred(SecurityContext securityContext, IdentityToken identit
for (int i = 0; i < certchain.length; i++) {
certchain[i] = new X509CertImpl(derval[i]);
if (logger.isLoggable(FINE)) {
logger.log(FINE, " " + certchain[i].getSubjectDN().getName());
logger.log(FINE, " " + certchain[i].getSubjectX500Principal()
.getName(X500Principal.RFC2253, CertificateRealm.OID_MAP));
}
}
if (logger.isLoggable(FINE)) {
Expand All @@ -353,7 +355,8 @@ private void createIdCred(SecurityContext securityContext, IdentityToken identit
* "dummy".
*
*/
X509CertificateCredential cred = new X509CertificateCredential(certchain, certchain[0].getSubjectDN().getName(),
X509CertificateCredential cred = new X509CertificateCredential(certchain,
certchain[0].getSubjectX500Principal().getName(X500Principal.RFC2253, CertificateRealm.OID_MAP),
"default");
if (logger.isLoggable(FINE)) {
logger.log(FINE, "Adding X509CertificateCredential to subject's PublicCredentials");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ public void setCurrentSecurityContext(Principal principal) {

private Subject createSubjectWithCerts(X509Certificate[] certificates) {
Subject subject = new Subject();

// Specifically not using getName() as we aren't interested with the name here, we're interested in the X500Principal itself
subject.getPublicCredentials().add(certificates[0].getSubjectX500Principal());
subject.getPublicCredentials().add(asList(certificates));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@

package org.glassfish.admin.amx.util.stringifier;

import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
import org.glassfish.admin.amx.util.StringUtil;

import javax.security.auth.x500.X500Principal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
Expand Down Expand Up @@ -91,8 +93,10 @@ public final class X509CertificateStringifier implements Stringifier
final StringBuilder buf = new StringBuilder();
final String NL = "\n";

buf.append("Issuer: ").append(cert.getIssuerDN().getName()).append(NL);
buf.append("Issued to: ").append(cert.getSubjectDN().getName()).append(NL);
buf.append("Issuer: ").append(cert.getIssuerX500Principal()
.getName(X500Principal.RFC2253, CertificateRealm.OID_MAP)).append(NL);
buf.append("Issued to: ").append(cert.getSubjectX500Principal()
.getName(X500Principal.RFC2253, CertificateRealm.OID_MAP)).append(NL);
buf.append("Version: ").append(cert.getVersion()).append(NL);
buf.append("Not valid before: ").append(cert.getNotBefore()).append(NL);
buf.append("Not valid after: ").append(cert.getNotAfter()).append(NL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@
import com.sun.enterprise.security.auth.realm.Realm;
import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;

import sun.security.x509.X500Name;

/**
* This class contains a collection of methods used by the JASPIC implementation to interact
* with the Payara JAAS/Realm system.
Expand Down Expand Up @@ -138,7 +136,7 @@ public static Subject jaasX500Login(Subject subject, X500Principal x500Principal

String callerPrincipalName = "";
try {
callerPrincipalName = x500Principal.getName(X500Principal.RFC1779);
callerPrincipalName = x500Principal.getName(X500Principal.RFC2253, CertificateRealm.OID_MAP);

privileged(() -> validSubject.getPublicCredentials().add(x500Principal));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,12 @@ public static void doX500Login(Subject subject, String appModuleID) throws Login
String realmName = null;
try {
X500Principal x500principal = getPublicCredentials(subject, X500Principal.class);
user = x500principal.getName();
if (x500principal == null) {
// Should never happen
return;
}

user = x500principal.getName(X500Principal.RFC2253, CertificateRealm.OID_MAP);

// In the RI-inherited implementation this directly creates
// some credentials and sets the security context. This means
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.x500.X500Principal;

import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
import org.glassfish.internal.api.Globals;
import org.glassfish.security.common.PrincipalImpl;

Expand Down Expand Up @@ -160,7 +162,8 @@ public boolean login() throws LoginException {
Enumeration<String> aliases = keyStore.aliases();
for (int i = 0; i < keyStore.size(); i++) {
aliasNames[i] = aliases.nextElement();
certificateNames[i] = ((X509Certificate) keyStore.getCertificate(aliasNames[i])).getSubjectDN().getName();
certificateNames[i] = ((X509Certificate) keyStore.getCertificate(aliasNames[i]))
.getSubjectX500Principal().getName(X500Principal.RFC2253, CertificateRealm.OID_MAP);
}

Callback[] callbacks = new Callback[] {createChoiceCallback(certificateNames)};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
package com.sun.enterprise.security.auth.realm.certificate;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

Expand All @@ -62,6 +65,7 @@
import java.util.LinkedList;
import java.util.logging.Level;
import javax.security.auth.callback.Callback;
import javax.security.auth.x500.X500Principal;


import org.jvnet.hk2.annotations.Service;
Expand Down Expand Up @@ -98,7 +102,31 @@ public final class CertificateRealm extends BaseRealm {

// Descriptive string of the authentication type of this realm.
public static final String AUTH_TYPE = "certificate";
private LinkedList<String> defaultGroups = new LinkedList<>();
public static final Map<String, String> OID_MAP;
static {
Map<String, String> oidMapInitialiser = new HashMap<>();
oidMapInitialiser.put(OIDs.UID, "UID");
oidMapInitialiser.put(OIDs.DC, "DC");
oidMapInitialiser.put(OIDs.EMAILADDRESS, "EMAILADDRESS");
oidMapInitialiser.put(OIDs.IP, "IP");
oidMapInitialiser.put(OIDs.CN, "CN");
oidMapInitialiser.put(OIDs.SURNAME, "SURNAME");
oidMapInitialiser.put(OIDs.SERIALNUMBER, "SERIALNUMBER");
oidMapInitialiser.put(OIDs.C, "C");
oidMapInitialiser.put(OIDs.L, "L");
oidMapInitialiser.put(OIDs.ST, "ST");
oidMapInitialiser.put(OIDs.STREET, "STREET");
oidMapInitialiser.put(OIDs.O, "O");
oidMapInitialiser.put(OIDs.OU, "OU");
oidMapInitialiser.put(OIDs.T, "T");
oidMapInitialiser.put(OIDs.GIVENNAME, "GIVENNAME");
oidMapInitialiser.put(OIDs.INITIALS, "INITIALS");
oidMapInitialiser.put(OIDs.GENERATION, "GENERATION");
oidMapInitialiser.put(OIDs.DNQUALIFIER, "DNQUALIFIER");
OID_MAP = Collections.unmodifiableMap(oidMapInitialiser);
}

private List<String> defaultGroups = new LinkedList<>();

/**
* Initialize a realm with some properties. This can be used when instantiating realms from their descriptions. This
Expand Down Expand Up @@ -164,18 +192,13 @@ public Enumeration getGroupNames(String username)
* Returns the name of all the groups that this user belongs to.
*
* @param subject The Subject object for the authentication request.
* @param principal The Principal object from the user certificate.
* @param callerPrincipal The Principal object from the user certificate.
*
*/
public void authenticate(Subject subject, Principal principal) {
// It is important to use x500name.getName() in order to be
// consistent with web containers view of the name - see bug
// 4646134 for reasons why this matters.
String name = principal.getName();

if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST, "Certificate realm setting up security context for: {0}", name);
}
public void authenticate(Subject subject, X500Principal callerPrincipal) {
// It is important to use X500Principal.getName() as that will
// return the LDAP name in RFC2253
String callerPrincipalName = callerPrincipal.getName(X500Principal.RFC2253, OID_MAP);

if (defaultGroups != null) {
Set<Principal> principalSet = subject.getPrincipals();
Expand All @@ -185,10 +208,10 @@ public void authenticate(Subject subject, Principal principal) {
}

if (!subject.getPrincipals().isEmpty()) {
subject.getPublicCredentials().add(new DistinguishedPrincipalCredential(principal));
subject.getPublicCredentials().add(new DistinguishedPrincipalCredential(callerPrincipal));
}

SecurityContext.setCurrent(new SecurityContext(name, subject));
SecurityContext.setCurrent(new SecurityContext(callerPrincipalName, subject));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) [2019] Payara Foundation and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://github.com/payara/Payara/blob/master/LICENSE.txt
* See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* The Payara Foundation designates this particular file as subject to the "Classpath"
* exception as provided by the Payara Foundation in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package com.sun.enterprise.security.auth.realm.certificate;

/**
* Class that contains the OID constants of various DN attributes
*/
public class OIDs {

public static final String UID = "0.9.2342.19200300.100.1.1"; // User ID
public static final String DC = "0.9.2342.19200300.100.1.25"; // Domain Component
public static final String EMAILADDRESS = "1.2.840.113549.1.9.1";
public static final String IP = "1.3.6.1.4.1.42.2.11.2.1"; // IP Address
public static final String CN = "2.5.4.3"; // Common Name
public static final String SURNAME = "2.5.4.4";
public static final String SERIALNUMBER = "2.5.4.5";
public static final String C = "2.5.4.6"; // Country
public static final String L = "2.5.4.7"; // Locality
public static final String ST = "2.5.4.8"; // State
public static final String STREET = "2.5.4.9";
public static final String O = "2.5.4.10"; // Organisation
public static final String OU = "2.5.4.11"; // Organisation Unit
public static final String T = "2.5.4.12"; // Title
public static final String GIVENNAME = "2.5.4.42";
public static final String INITIALS = "2.5.4.43";
public static final String GENERATION = "2.5.4.44";
public static final String DNQUALIFIER = "2.5.4.46";

}
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ public void signJar(File input, ZipOutputStream zout, String alias, final Attrib
sig.update(sigFileContent);

// Create PKCS7 block
// Can't use X500Principal here as SignerInfo requires X500Name
PKCS7 pkcs7 = new PKCS7(new AlgorithmId[] { AlgorithmId.get(digestAlgorithm) }, new ContentInfo(sigFileContent), certChain,
new SignerInfo[] { new SignerInfo((X500Name) certChain[0].getIssuerDN(), certChain[0].getSerialNumber(),
AlgorithmId.get(digestAlgorithm), AlgorithmId.get(keyAlgorithm), sig.sign()) });
Expand Down

0 comments on commit f8f2450

Please sign in to comment.