3131import javax .security .auth .x500 .X500Principal ;
3232import org .apache .zookeeper .KeeperException ;
3333import org .apache .zookeeper .common .ClientX509Util ;
34- import org .apache .zookeeper .common .X509Exception ;
3534import org .apache .zookeeper .common .X509Exception .KeyManagerException ;
3635import org .apache .zookeeper .common .X509Exception .TrustManagerException ;
3736import org .apache .zookeeper .common .X509Util ;
@@ -61,12 +60,14 @@ public class X509AuthenticationProvider implements AuthenticationProvider {
6160 * The following System Property keys are used to extract clientId from the client cert.
6261 * @see #getClientId(X509Certificate)
6362 */
64- public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDTYPE = "zookeeper.X509AuthenticationProvider.clientCertIdType" ;
65- public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANMATCHTYPE = "zookeeper.X509AuthenticationProvider.clientCertIdSanMatchType" ;
63+ public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_TYPE = "zookeeper.X509AuthenticationProvider.clientCertIdType" ;
64+ public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_MATCH_TYPE = "zookeeper.X509AuthenticationProvider.clientCertIdSanMatchType" ;
6665 // Match Regex is used to choose which entry to use
67- public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANMATCHREGEX = "zookeeper.X509AuthenticationProvider.clientCertIdSanMatchRegex" ;
66+ public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_MATCH_REGEX = "zookeeper.X509AuthenticationProvider.clientCertIdSanMatchRegex" ;
6867 // Extract Regex is used to construct a client ID (acl entity) to return
69- public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANEXTRACTREGEX = "zookeeper.X509AuthenticationProvider.clientCertIdSanExtractRegex" ;
68+ public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_EXTRACT_REGEX = "zookeeper.X509AuthenticationProvider.clientCertIdSanExtractRegex" ;
69+ // Specifies match group index for the extract regex (i in Matcher.group(i))
70+ public static final String ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_EXTRACT_MATCHER_GROUP_INDEX = "zookeeper.X509AuthenticationProvider.clientCertIdSanExtractMatcherGroupIndex" ;
7071
7172 static final Logger LOG = LoggerFactory .getLogger (X509AuthenticationProvider .class );
7273 private final X509TrustManager trustManager ;
@@ -196,11 +197,11 @@ public KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte[] authDat
196197 */
197198 protected String getClientId (X509Certificate clientCert ) {
198199 String clientCertIdType =
199- System .getProperty (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDTYPE );
200+ System .getProperty (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_TYPE );
200201 if (clientCertIdType != null && clientCertIdType .equalsIgnoreCase ("SAN" )) {
201202 try {
202203 return matchAndExtractSAN (clientCert );
203- } catch (CertificateException | IllegalArgumentException ce ) {
204+ } catch (Exception ce ) {
204205 LOG .warn ("X509AuthenticationProvider::getClientId(): failed to match and extract a"
205206 + " client ID from SAN! Using Subject DN instead..." , ce );
206207 }
@@ -212,14 +213,18 @@ protected String getClientId(X509Certificate clientCert) {
212213 private String matchAndExtractSAN (X509Certificate clientCert )
213214 throws CertificateParsingException {
214215 Integer matchType =
215- Integer .getInteger (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANMATCHTYPE );
216+ Integer .getInteger (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_MATCH_TYPE );
216217 String matchRegex =
217- System .getProperty (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANMATCHREGEX );
218+ System .getProperty (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_MATCH_REGEX );
218219 String extractRegex =
219- System .getProperty (ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENTCERTIDSANEXTRACTREGEX );
220+ System .getProperty (
221+ ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_EXTRACT_REGEX );
222+ Integer extractMatcherGroupIndex = Integer .getInteger (
223+ ZOOKEEPER_X509AUTHENTICATIONPROVIDER_CLIENT_CERT_ID_SAN_EXTRACT_MATCHER_GROUP_INDEX );
220224 LOG .info ("X509AuthenticationProvider::matchAndExtractSAN(): Using SAN in the client cert "
221- + "for client ID! matchType: {}, matchRegex: {}, extractRegex: {}" , matchType ,
222- matchRegex , extractRegex );
225+ + "for client ID! matchType: {}, matchRegex: {}, extractRegex: {}, "
226+ + "extractMatcherGroupIndex: {}" , matchType , matchRegex , extractRegex ,
227+ extractMatcherGroupIndex );
223228 if (matchType == null || matchRegex == null || extractRegex == null || matchType < 0
224229 || matchType > 8 ) {
225230 // SAN extension must be in the range of [0, 8].
@@ -259,9 +264,12 @@ private String matchAndExtractSAN(X509Certificate clientCert)
259264 Pattern extractPattern = Pattern .compile (extractRegex );
260265 Matcher matcher = extractPattern .matcher (matched .iterator ().next ().get (1 ).toString ());
261266 if (matcher .find ()) {
262- String result = matcher .group ();
267+ // If extractMatcherGroupIndex is not given, return the 1st index by default
268+ extractMatcherGroupIndex =
269+ extractMatcherGroupIndex == null ? 1 : extractMatcherGroupIndex ;
270+ String result = matcher .group (extractMatcherGroupIndex );
263271 LOG .info ("X509AuthenticationProvider::matchAndExtractSAN(): returning extracted "
264- + "client ID: {}" , result );
272+ + "client ID: {} using Matcher group index: {} " , result , extractMatcherGroupIndex );
265273 return result ;
266274 }
267275 String errStr = "X509AuthenticationProvider::matchAndExtractSAN(): failed to find an "
0 commit comments