Great, thanks! Colm.
On Fri, Jan 26, 2018 at 8:24 AM, Li, Jiajia <[email protected]> wrote: > The error occurred after upgrading the mvn version to 3.5.2, I've fixed > it. Thanks Colm. > > Regards, > Jiajia > > -----Original Message----- > From: Colm O hEigeartaigh [mailto:[email protected]] > Sent: Thursday, January 25, 2018 5:43 PM > To: Li, Jiajia <[email protected]> > Cc: [email protected] > Subject: Re: directory-kerby git commit: DIRKRB-681 Add new LoginModule > > Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; > 2017-10-18T08:58:13+01:00) > Maven home: /opt/apache-maven-3.5.2 > Java version: 1.8.0_151, vendor: Oracle Corporation Java home: > /opt/jdk1.8.0_151/jre Default locale: en_GB, platform encoding: UTF-8 OS > name: "linux", version: "4.13.0-25-generic", arch: "amd64", family: > "unix" > > Is the modernizer plugin running when you do "mvn clean install"? > > Colm. > > On Thu, Jan 25, 2018 at 8:13 AM, Li, Jiajia <[email protected]> wrote: > > > Hi Colm, > > > > > > > > I can’t reproduce this build failure, could you provide the java and > > OS version? > > > > > > > > Thanks, > > > > Jiajia > > > > > > > > *From:* Colm O hEigeartaigh [mailto:[email protected]] > > *Sent:* Wednesday, January 24, 2018 11:30 PM > > *To:* [email protected]; Li, Jiajia <[email protected]> > > *Subject:* Re: directory-kerby git commit: DIRKRB-681 Add new > > LoginModule > > > > > > > > Hi Jiajia, > > > > This commit is causing a build failure: > > > > [INFO] --- modernizer-maven-plugin:1.5.0:modernizer (modernizer-check) > > @ has-client --- [ERROR] > > /home/colm/src/apache/directory-kerby/has-project/ > > has-client/src/main/java/org/apache/kerby/has/client/ > HasLoginModule.java:160: > > Prefer java.lang.StringBuilder > > [ERROR] /home/colm/src/apache/directory-kerby/has-project/ > > has-client/src/main/java/org/apache/kerby/has/client/ > HasLoginModule.java:163: > > Prefer java.lang.StringBuilder > > > > Colm. > > > > > > > > On Mon, Jan 22, 2018 at 3:28 AM, <[email protected]> wrote: > > > > Repository: directory-kerby > > Updated Branches: > > refs/heads/trunk a8a284d9c -> 34ccabec6 > > > > > > DIRKRB-681 Add new LoginModule > > > > > > Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo > > Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/ > > commit/34ccabec > > Tree: > > http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/34ccabec > > Diff: > > http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/34ccabec > > > > Branch: refs/heads/trunk > > Commit: 34ccabec68b2b83b683240801e3929ef43eec26e > > Parents: a8a284d > > Author: plusplusjiajia <[email protected]> > > Authored: Mon Jan 22 11:25:06 2018 +0800 > > Committer: plusplusjiajia <[email protected]> > > Committed: Mon Jan 22 11:25:06 2018 +0800 > > > > ---------------------------------------------------------------------- > > .../apache/kerby/has/client/HasLoginModule.java | 456 > > +++++++++++++++++++ > > 1 file changed, 456 insertions(+) > > ---------------------------------------------------------------------- > > > > > > http://git-wip-us.apache.org/repos/asf/directory-kerby/ > > blob/34ccabec/has-project/has-client/src/main/java/org/ > > apache/kerby/has/client/HasLoginModule.java > > ---------------------------------------------------------------------- > > diff --git > > a/has-project/has-client/src/main/java/org/apache/kerby/has/client/Has > > LoginModule.java > > b/has-project/has-client/src/main/java/org/apache/kerby/ > > has/client/HasLoginModule.java > > new file mode 100644 > > index 0000000..8debda5 > > --- /dev/null > > +++ b/has-project/has-client/src/main/java/org/apache/kerby/ > > has/client/HasLoginModule.java > > @@ -0,0 +1,456 @@ > > +/** > > + * Licensed to the Apache Software Foundation (ASF) under one > > + * or more contributor license agreements. See the NOTICE file > > + * distributed with this work for additional information > > + * regarding copyright ownership. The ASF licenses this file > > + * to you under the Apache License, Version 2.0 (the > > + * "License"); you may not use this file except in compliance > > + * with the License. You may obtain a copy of the License at > > + * <p> > > + * http://www.apache.org/licenses/LICENSE-2.0 > > + * <p> > > + * Unless required by applicable law or agreed to in writing, > > + * software distributed under the License is distributed on an > > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > > + * KIND, either express or implied. See the License for the > > + * specific language governing permissions and limitations > > + * under the License. > > + */ > > +package org.apache.kerby.has.client; > > + > > +import com.sun.security.auth.module.Krb5LoginModule; > > +import org.apache.kerby.has.common.HasException; > > +import org.apache.kerby.kerberos.kerb.ccache.Credential; > > +import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket; > > +import org.slf4j.Logger; > > +import org.slf4j.LoggerFactory; > > +import sun.security.jgss.krb5.Krb5Util; import > > +sun.security.krb5.Credentials; import sun.security.krb5.KrbException; > > +import sun.security.krb5.PrincipalName; > > + > > +import javax.security.auth.DestroyFailedException; > > +import javax.security.auth.Subject; > > +import javax.security.auth.callback.CallbackHandler; > > +import javax.security.auth.kerberos.KerberosPrincipal; > > +import javax.security.auth.kerberos.KerberosTicket; > > +import javax.security.auth.login.LoginException; > > +import javax.security.auth.spi.LoginModule; > > +import java.io.IOException; > > +import java.security.Principal; > > +import java.util.Date; > > +import java.util.Iterator; > > +import java.util.Map; > > +import java.util.Set; > > + > > +/** > > + * This <code>LoginModule</code> authenticates users using tgt ticket > > + * The client's TGT will be retrieved from the API of HasClient */ > > +public class HasLoginModule implements LoginModule { > > + > > + public static final Logger LOG = LoggerFactory.getLogger( > > HasLoginModule.class); > > + > > + Krb5LoginModule krb5LoginModule; > > + > > + // initial state > > + private Subject subject; > > + > > + // configurable option > > + private boolean debug = false; > > + private boolean doNotPrompt = false; > > + private boolean useTgtTicket = false; > > + private String hadoopSecurityHas = null; > > + private String princName = null; > > + > > + private boolean refreshKrb5Config = false; > > + > > + // specify if initiator. > > + // perform authentication exchange if initiator > > + private boolean isInitiator = true; > > + > > + // the authentication status > > + private boolean succeeded = false; > > + private boolean commitSucceeded = false; > > + > > + private Credentials cred = null; > > + > > + private PrincipalName principal = null; > > + private KerberosPrincipal kerbClientPrinc = null; > > + private KerberosTicket kerbTicket = null; > > + private StringBuffer krb5PrincName = null; > > + private boolean unboundServer = false; > > + > > + /** > > + * Initialize this <code>LoginModule</code>. > > + * > > + * @param subject the <code>Subject</code> to be > > authenticated. <p> > > + * @param callbackHandler a <code>CallbackHandler</code> for > > + * communication with the end user (prompting > > for > > + * usernames and passwords, for example). <p> > > + * @param sharedState shared <code>LoginModule</code> state. <p> > > + * @param options options specified in the login > > + * <code>Configuration</code> for this > > particular > > + * <code>LoginModule</code>. > > + */ > > + public void initialize(Subject subject, > > + CallbackHandler callbackHandler, > > + Map<String, ?> sharedState, > > + Map<String, ?> options) { > > + > > + this.subject = subject; > > + > > + // initialize any configured options > > + useTgtTicket = "true".equalsIgnoreCase((String) > > options.get("useTgtTicket")); > > + > > + if (useTgtTicket) { > > + debug = "true".equalsIgnoreCase((String) > > options.get("debug")); > > + doNotPrompt = "true".equalsIgnoreCase((String) > > options.get("doNotPrompt")); > > + useTgtTicket = "true".equalsIgnoreCase((String) > > options.get("useTgtTicket")); > > + hadoopSecurityHas = (String) options.get(" > > hadoopSecurityHas"); > > + princName = (String) options.get("principal"); > > + refreshKrb5Config = > > + "true".equalsIgnoreCase((String) options.get(" > > refreshKrb5Config")); > > + > > + // check isInitiator value > > + String isInitiatorValue = ((String) > > options.get("isInitiator")); > > + if (isInitiatorValue != null) { > > + // use default, if value not set > > + isInitiator = "true".equalsIgnoreCase( > isInitiatorValue); > > + } > > + > > + if (debug) { > > + System.out.print("Debug is " + debug > > + + " doNotPrompt " + doNotPrompt > > + + " isInitiator " + isInitiator > > + + " refreshKrb5Config is " + refreshKrb5Config > > + + " principal is " + princName + "\n"); > > + } > > + } else { > > + krb5LoginModule = new Krb5LoginModule(); > > + krb5LoginModule.initialize(subject, callbackHandler, > > sharedState, options); > > + } > > + } > > + > > + /** > > + * Authenticate the user > > + * > > + * @return true in all cases since this <code>LoginModule</code> > > + * should not be ignored. > > + * @throws LoginException if this <code>LoginModule</code> > > + * is unable to perform the > > authentication. > > + */ > > + public boolean login() throws LoginException { > > + > > + if (useTgtTicket) { > > + if (refreshKrb5Config) { > > + try { > > + if (debug) { > > + System.out.println("Refreshing Kerberos > > configuration"); > > + } > > + sun.security.krb5.Config.refresh(); > > + } catch (KrbException ke) { > > + LoginException le = new > > + LoginException(ke.getMessage() > > ); > > + le.initCause(ke); > > + throw le; > > + } > > + } > > + String principalProperty = System.getProperty("sun. > > security.krb5.principal"); > > + if (principalProperty != null) { > > + krb5PrincName = new StringBuffer(principalProperty); > > + } else { > > + if (princName != null) { > > + krb5PrincName = new StringBuffer(princName); > > + } > > + } > > + > > + validateConfiguration(); > > + > > + if (krb5PrincName != null && > > + krb5PrincName.toString().equals("*")) > > { > > + unboundServer = true; > > + } > > + > > + // attempt the authentication by getting the username and > pwd > > + // by prompting or configuration i.e. not from shared > > + state > > + > > + try { > > + attemptAuthentication(); > > + succeeded = true; > > + cleanState(); > > + return true; > > + } catch (LoginException e) { > > + // authentication failed -- clean out state > > + if (debug) { > > + System.out.println("\t\t[HasLoginModule] " > > + + "authentication failed \n" > > + + e.getMessage()); > > + } > > + succeeded = false; > > + cleanState(); > > + throw e; > > + } > > + } else { > > + succeeded = krb5LoginModule.login(); > > + return succeeded; > > + } > > + } > > + > > + /** > > + * Process the configuration options > > + * Get the TGT from Has Client > > + */ > > + private void attemptAuthentication() > > + throws LoginException { > > + > > + /* > > + * Check the creds cache to see whether > > + * we have TGT for this client principal > > + */ > > + if (krb5PrincName != null) { > > + try { > > + principal = new PrincipalName(krb5PrincName.toString(), > > + PrincipalName.KRB_NT_PRINCIPAL); > > + } catch (KrbException e) { > > + LoginException le = new LoginException(e.getMessage()); > > + le.initCause(e); > > + throw le; > > + } > > + } > > + > > + try { > > + if (useTgtTicket) { > > + if (debug) { > > + System.out.println("use tgt ticket to login, > > + acquire > > TGT TICKET..."); > > + } > > + > > + HasClient hasClient = new HasClient(hadoopSecurityHas); > > + TgtTicket tgtTicket = null; > > + try { > > + tgtTicket = hasClient.requestTgt(); > > + } catch (HasException e) { > > + LoginException le = new > > + LoginException(e.getMessage()) > > ; > > + le.initCause(e); > > + throw le; > > + } > > + Credential credential = new Credential(tgtTicket); > > + boolean[] flags = new boolean[7]; > > + int flag = credential.getTicketFlags().getFlags(); > > + for (int i = 6; i >= 0; i--) { > > + flags[i] = (flag & (1 << i)) != 0; > > + } > > + Date startTime = null; > > + if (credential.getStartTime() != null) { > > + startTime = credential.getStartTime().getValue(); > > + } > > + cred = new Credentials(credential.getTicket().encode(), > > + credential.getClientName().getName(), > > + credential.getServerName().getName(), > > + credential.getKey().getKeyData(), > > + credential.getKey().getKeyType().getValue(), > > + flags, > > + credential.getAuthTime().getValue(), > > + startTime, > > + credential.getEndTime().getValue(), > > + credential.getRenewTill().getValue(), > > + null); > > + > > + // get the principal name from the ticket cache > > + if (cred != null && principal == null) { > > + principal = cred.getClient(); > > + } > > + if (debug) { > > + System.out.println("Principal is " + principal); > > + if (cred == null) { > > + System.out.println("null credentials from TGT > > Ticket"); > > + } > > + } > > + } > > + } catch (KrbException e) { > > + LoginException le = new LoginException(e.getMessage()); > > + le.initCause(e); > > + throw le; > > + } catch (IOException ioe) { > > + LoginException ie = new LoginException(ioe.getMessage()); > > + ie.initCause(ioe); > > + throw ie; > > + } > > + } > > + > > + private void validateConfiguration() throws LoginException { > > + if (doNotPrompt && !useTgtTicket) { > > + throw new LoginException("Configuration Error" > > + + " - either doNotPrompt should be " > > + + " false or" > > + + " useTgtTicket" > > + + " should be true"); > > + } > > + > > + if (krb5PrincName != null && > > + krb5PrincName.toString().equals("*") > > && isInitiator) { > > + throw new LoginException("Configuration Error" > > + + " - principal cannot be * when isInitiator is true"); > > + } > > + } > > + > > + /** > > + * <p> This method is called if the LoginContext's > > + * overall authentication succeeded > > + * > > + * @return true if this LoginModule's own login and commit > > + * attempts succeeded, or false otherwise. > > + * @throws LoginException if the commit fails. > > + */ > > + > > + public boolean commit() throws LoginException { > > + if (debug) { > > + System.out.println("Login success? " + succeeded); > > + } > > + > > + if (useTgtTicket) { > > + if (succeeded == false) { > > + return false; > > + } else { > > + if (isInitiator && cred == null) { > > + succeeded = false; > > + throw new LoginException("Null Client Credential"); > > + } > > + > > + if (subject.isReadOnly()) { > > + cleanKerberosCred(); > > + throw new LoginException("Subject is Readonly"); > > + } > > + > > + Set<Object> privCredSet = > > + subject.getPrivateCredentials( > > ); > > + Set<Principal> princSet = subject.getPrincipals(); > > + kerbClientPrinc = new KerberosPrincipal(principal. > > getName()); > > + > > + // create Kerberos Ticket > > + if (isInitiator) { > > + kerbTicket = Krb5Util.credsToTicket(cred); > > + } > > + > > + // Let us add the kerbClientPrinc,kerbTicket > > + > > + // We won't add "*" as a KerberosPrincipal > > + if (!unboundServer > > + && !princSet.contains(kerbClientPrinc)) { > > + princSet.add(kerbClientPrinc); > > + } > > + > > + // add the TGT > > + if (kerbTicket != null && > > + privCredSet.contains(kerbTicket)) > > { > > + privCredSet.add(kerbTicket); > > + } > > + } > > + commitSucceeded = true; > > + if (debug) { > > + System.out.println("Commit Succeeded \n"); > > + } > > + return true; > > + } else { > > + return krb5LoginModule.commit(); > > + } > > + } > > + > > + /** > > + * <p> This method is called if the LoginContext's > > + * overall authentication failed. > > + * > > + * @return false if this LoginModule's own login and/or commit > > attempts > > + * failed, and true otherwise. > > + * @throws LoginException if the abort fails. > > + */ > > + > > + public boolean abort() throws LoginException { > > + if (useTgtTicket) { > > + if (succeeded == false) { > > + return false; > > + } else if (succeeded == true && commitSucceeded == false) { > > + // login succeeded but overall authentication failed > > + succeeded = false; > > + cleanKerberosCred(); > > + } else { > > + // overall authentication succeeded and commit > succeeded, > > + // but someone else's commit failed > > + logout(); > > + } > > + return true; > > + } else { > > + return krb5LoginModule.abort(); > > + } > > + } > > + > > + /** > > + * Logout the user. > > + * > > + * @return true in all cases since this <code>LoginModule</code> > > + * should not be ignored. > > + * @throws LoginException if the logout fails. > > + */ > > + public boolean logout() throws LoginException { > > + > > + if (useTgtTicket) { > > + if (debug) { > > + System.out.println("\t\t[Krb5LoginModule]: " > > + + "Entering logout"); > > + } > > + > > + if (subject.isReadOnly()) { > > + cleanKerberosCred(); > > + throw new LoginException("Subject is Readonly"); > > + } > > + > > + subject.getPrincipals().remove(kerbClientPrinc); > > + // Let us remove all Kerberos credentials stored in the > > Subject > > + Iterator<Object> it = subject.getPrivateCredentials( > > ).iterator(); > > + while (it.hasNext()) { > > + Object o = it.next(); > > + if (o instanceof KerberosTicket) { > > + it.remove(); > > + } > > + } > > + // clean the kerberos ticket and keys > > + cleanKerberosCred(); > > + > > + succeeded = false; > > + commitSucceeded = false; > > + if (debug) { > > + System.out.println("\t\t[HasLoginModule]: " > > + + "logged out Subject"); > > + } > > + return true; > > + } else { > > + return krb5LoginModule.logout(); > > + } > > + } > > + > > + /** > > + * Clean Kerberos credentials > > + */ > > + private void cleanKerberosCred() throws LoginException { > > + // Clean the ticket and server key > > + try { > > + if (kerbTicket != null) { > > + kerbTicket.destroy(); > > + } > > + } catch (DestroyFailedException e) { > > + throw new LoginException("Destroy Failed on Kerberos > > + Private > > Credentials"); > > + } > > + kerbTicket = null; > > + kerbClientPrinc = null; > > + } > > + > > + /** > > + * Clean out the state > > + */ > > + private void cleanState() { > > + > > + if (!succeeded) { > > + // remove temp results for the next try > > + principal = null; > > + } > > + if (krb5PrincName != null && krb5PrincName.length() != 0) { > > + krb5PrincName.delete(0, krb5PrincName.length()); > > + } > > + krb5PrincName = null; > > + } > > +} > > > > > > > > > > > > -- > > > > Colm O hEigeartaigh > > > > Talend Community Coder > > http://coders.talend.com > > > > > > -- > Colm O hEigeartaigh > > Talend Community Coder > http://coders.talend.com > -- Colm O hEigeartaigh Talend Community Coder http://coders.talend.com
