Code formatting Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/34098dac Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/34098dac Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/34098dac
Branch: refs/heads/master Commit: 34098dac637f452f8a14ef19cc55511b6d261924 Parents: 5bb8366 Author: Guillaume Nodet <[email protected]> Authored: Wed Jul 17 09:03:35 2013 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Wed Jul 17 09:03:35 2013 +0200 ---------------------------------------------------------------------- .../apache/sshd/server/HandshakingUserAuth.java | 96 ++-- .../sshd/server/auth/gss/CredentialHelper.java | 162 +++--- .../sshd/server/auth/gss/GSSAuthenticator.java | 180 +++--- .../sshd/server/auth/gss/UserAuthGSS.java | 550 +++++++++---------- .../sshd/server/session/ServerSession.java | 106 ++-- 5 files changed, 539 insertions(+), 555 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/34098dac/sshd-core/src/main/java/org/apache/sshd/server/HandshakingUserAuth.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/HandshakingUserAuth.java b/sshd-core/src/main/java/org/apache/sshd/server/HandshakingUserAuth.java index 485e00f..625f7ba 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/HandshakingUserAuth.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/HandshakingUserAuth.java @@ -24,57 +24,55 @@ import org.apache.sshd.server.session.ServerSession; /** * Extension of UserAuth for use with methods which require handshakes, such as gssapi-with-mic. - * + * * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public interface HandshakingUserAuth extends UserAuth { - - /** - * Set the service name from the original request. This may be required for MIC verification later. - * - * @param service The service name - */ - - void setServiceName(String service); - - /** - * Check whether a particular message is handled here. - * - * @param msg The message - * - * @return <code>true</code> if the message is handled - */ - - boolean handles(SshConstants.Message msg); - - /** - * Handle another step in the authentication process. - * - * @param session the current ssh session - * @param msg The message type - * @param buffer the request buffer containing parameters specific to this request - * @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication - * is not finished yet - * @throws Exception if the authentication fails - */ - - Boolean next(ServerSession session, SshConstants.Message msg, Buffer buffer) throws Exception; - - /** - * Get a user name which has been derived from the handshaking process, or the intial name if - * nothing has been found. - * - * @return The user name - * - * @throws Exception if the request fails - */ - - String getUserName() throws Exception; - - /** - * Free any system resources used by the module. - */ - - void destroy(); + + /** + * Set the service name from the original request. This may be required for MIC verification later. + * + * @param service The service name + */ + + void setServiceName(String service); + + /** + * Check whether a particular message is handled here. + * + * @param msg The message + * @return <code>true</code> if the message is handled + */ + + boolean handles(SshConstants.Message msg); + + /** + * Handle another step in the authentication process. + * + * @param session the current ssh session + * @param msg The message type + * @param buffer the request buffer containing parameters specific to this request + * @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication + * is not finished yet + * @throws Exception if the authentication fails + */ + + Boolean next(ServerSession session, SshConstants.Message msg, Buffer buffer) throws Exception; + + /** + * Get a user name which has been derived from the handshaking process, or the intial name if + * nothing has been found. + * + * @return The user name + * @throws Exception if the request fails + */ + + String getUserName() throws Exception; + + /** + * Free any system resources used by the module. + */ + + void destroy(); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/34098dac/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/CredentialHelper.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/CredentialHelper.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/CredentialHelper.java index 91cca9f..37ce5d3 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/CredentialHelper.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/CredentialHelper.java @@ -39,94 +39,92 @@ import org.ietf.jgss.GSSManager; */ public class CredentialHelper { - - public static GSSCredential creds(GSSManager mgr, String spn, String keytab) throws LoginException, GSSException { - LoginContext lc = new LoginContext("x", null, null, new FixedLoginConfiguration(spn, keytab)); - - lc.login(); - - try { - return (GSSCredential) Subject.doAs(lc.getSubject(), new G(mgr)); - } catch (PrivilegedActionException e) { - throw (GSSException) e.getCause(); - } - } - - /** - * A login configuration which is defined from code. - * - * @author Richard Evans - */ - - private static class FixedLoginConfiguration extends Configuration { - - private AppConfigurationEntry entry; - - /** - * Constructor. - */ - - private FixedLoginConfiguration(String spn, String keytab) { - Map<String, String> parms = new HashMap<String, String>(); - - parms.put("isInitiator", "false"); - parms.put("principal", spn); - parms.put("useKeyTab", "true"); - parms.put("storeKey", "true"); - - if (keytab != null) { - parms.put("keyTab", keytab); - } - - entry = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, parms); - } - - /** - * Get the configuration entries for a name. - * - * @param name The name - * - * @return The entries, or <code>null</code> if the name is not known - */ - - public AppConfigurationEntry[] getAppConfigurationEntry(String name) { - return new AppConfigurationEntry [] { entry }; - } - /** - * Refresh the configuration. Nothing to do here. - */ - - public void refresh() { + public static GSSCredential creds(GSSManager mgr, String spn, String keytab) throws LoginException, GSSException { + LoginContext lc = new LoginContext("x", null, null, new FixedLoginConfiguration(spn, keytab)); + + lc.login(); + + try { + return (GSSCredential) Subject.doAs(lc.getSubject(), new G(mgr)); + } catch (PrivilegedActionException e) { + throw (GSSException) e.getCause(); + } } - } - - /** - * Privileged action which runs as the subject to get the credentials. - */ - - private static final class G implements PrivilegedExceptionAction<GSSCredential> { - - private GSSManager mgr; - + /** - * @param mgr The existing GSS manager + * A login configuration which is defined from code. + * + * @author Richard Evans */ - - private G(GSSManager mgr) { - this.mgr = mgr; + + private static class FixedLoginConfiguration extends Configuration { + + private AppConfigurationEntry entry; + + /** + * Constructor. + */ + + private FixedLoginConfiguration(String spn, String keytab) { + Map<String, String> parms = new HashMap<String, String>(); + + parms.put("isInitiator", "false"); + parms.put("principal", spn); + parms.put("useKeyTab", "true"); + parms.put("storeKey", "true"); + + if (keytab != null) { + parms.put("keyTab", keytab); + } + + entry = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule", AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, parms); + } + + /** + * Get the configuration entries for a name. + * + * @param name The name + * @return The entries, or <code>null</code> if the name is not known + */ + + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + return new AppConfigurationEntry[]{entry}; + } + + /** + * Refresh the configuration. Nothing to do here. + */ + + public void refresh() { + } } - + /** - * Do the action. - * - * @return The new credentials - * - * @throws GSSException If an error occurred + * Privileged action which runs as the subject to get the credentials. */ - - public GSSCredential run() throws GSSException { - return mgr.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, UserAuthGSS.KRB5_MECH, GSSCredential.ACCEPT_ONLY); + + private static final class G implements PrivilegedExceptionAction<GSSCredential> { + + private GSSManager mgr; + + /** + * @param mgr The existing GSS manager + */ + + private G(GSSManager mgr) { + this.mgr = mgr; + } + + /** + * Do the action. + * + * @return The new credentials + * @throws GSSException If an error occurred + */ + + public GSSCredential run() throws GSSException { + return mgr.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, UserAuthGSS.KRB5_MECH, GSSCredential.ACCEPT_ONLY); + } } - } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/34098dac/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/GSSAuthenticator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/GSSAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/GSSAuthenticator.java index fd988b9..96ef66b 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/GSSAuthenticator.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/GSSAuthenticator.java @@ -31,101 +31,97 @@ import org.ietf.jgss.GSSManager; /** * Class providing basic GSS authentication services. Can be used as-is, but is often extended to provide environment * specific implementations. - * + * * @author Richard Evans */ public class GSSAuthenticator { - - // Options: - // - // Service principal name: if unset, use host/hostname - - private String servicePrincipalName; - - // Location of Kerberos key table; if unset use default - - private String keytabFile; - - /** - * Overridable method to get GSS manager suitable for current environment. - * - * @return A new manager - */ - - public GSSManager getGSSManager() { - return GSSManager.getInstance(); - } - - /** - * Overridable method to get GSS accept credential suitable for the current environment. The default - * implementation uses a Kerberos key table. - * - * @param mgr The GSS manager - * - * @return The credential; if the result is <code>null</code> gssapi authentication fails immediately - * - * @throws UnknownHostException If the local host name could not be determined - * @throws LoginException If the subject could not be found - * @throws GSSException If the credential could not be obtained - */ - - public GSSCredential getGSSCredential(GSSManager mgr) throws UnknownHostException, LoginException, GSSException { - - String name = servicePrincipalName; - - if (name == null) { - name = "host/" + InetAddress.getLocalHost().getCanonicalHostName(); + + // Options: + // + // Service principal name: if unset, use host/hostname + + private String servicePrincipalName; + + // Location of Kerberos key table; if unset use default + + private String keytabFile; + + /** + * Overridable method to get GSS manager suitable for current environment. + * + * @return A new manager + */ + + public GSSManager getGSSManager() { + return GSSManager.getInstance(); + } + + /** + * Overridable method to get GSS accept credential suitable for the current environment. The default + * implementation uses a Kerberos key table. + * + * @param mgr The GSS manager + * @return The credential; if the result is <code>null</code> gssapi authentication fails immediately + * @throws UnknownHostException If the local host name could not be determined + * @throws LoginException If the subject could not be found + * @throws GSSException If the credential could not be obtained + */ + + public GSSCredential getGSSCredential(GSSManager mgr) throws UnknownHostException, LoginException, GSSException { + + String name = servicePrincipalName; + + if (name == null) { + name = "host/" + InetAddress.getLocalHost().getCanonicalHostName(); + } + + return CredentialHelper.creds(mgr, name, keytabFile); + } + + /** + * Validate the user name passed in the initial SSH_MSG_USERAUTH_REQUEST message. This is sort of mandated by RFC 4462, but it + * may be more useful to wait for the GSS negotiation to complete. The default implementation here always succeeds. + * + * @param session The current session + * @param user The user name from the initial request + * @return <code>true</code> if the user is valid, <code>false</code> if invalid + */ + + public boolean validateInitialUser(ServerSession session, String user) { + return true; + } + + /** + * Validate the source identity obtained from the context after negotiation is complete. + * The default implementation here always succeeds. + * + * @param session The current session + * @param identity The identity from the GSS context + * @return <code>true</code> if the identity is valid, <code>false</code> if invalid + */ + + public boolean validateIdentity(ServerSession session, String identity) { + return true; + } + + /** + * Set the service principal name to be used. The default is host/hostname. + * + * @param servicePrincipalName The principal name + */ + + public void setServicePrincipalName(String servicePrincipalName) { + this.servicePrincipalName = servicePrincipalName; + } + + /** + * Set the location of the Kerberos keytab. The default is defined by the JRE. + * + * @param keytabFile The location of the keytab + */ + + public void setKeytabFile(String keytabFile) { + this.keytabFile = keytabFile; } - - return CredentialHelper.creds(mgr, name, keytabFile); - } - - /** - * Validate the user name passed in the initial SSH_MSG_USERAUTH_REQUEST message. This is sort of mandated by RFC 4462, but it - * may be more useful to wait for the GSS negotiation to complete. The default implementation here always succeeds. - * - * @param session The current session - * @param user The user name from the initial request - * - * @return <code>true</code> if the user is valid, <code>false</code> if invalid - */ - - public boolean validateInitialUser(ServerSession session, String user) { - return true; - } - - /** - * Validate the source identity obtained from the context after negotiation is complete. - * The default implementation here always succeeds. - * - * @param session The current session - * @param identity The identity from the GSS context - * - * @return <code>true</code> if the identity is valid, <code>false</code> if invalid - */ - - public boolean validateIdentity(ServerSession session, String identity) { - return true; - } - - /** - * Set the service principal name to be used. The default is host/hostname. - * - * @param servicePrincipalName The principal name - */ - - public void setServicePrincipalName(String servicePrincipalName) { - this.servicePrincipalName = servicePrincipalName; - } - - /** - * Set the location of the Kerberos keytab. The default is defined by the JRE. - * - * @param keytabFile The location of the keytab - */ - - public void setKeytabFile(String keytabFile) { - this.keytabFile = keytabFile; - } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/34098dac/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java index c2518dc..afcca3a 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java @@ -36,304 +36,296 @@ import org.slf4j.LoggerFactory; /** * Prototype user authentication handling gssapi-with-mic. Implements <code>HandshakingUserAuth</code> because * the process involves several steps. - * + * <p/> * Several methods are available for overriding in specific circumstances. */ public class UserAuthGSS implements HandshakingUserAuth { - - // Oids for the Kerberos 5 mechanism and principal - - public static final Oid KRB5_MECH = createOID("1.2.840.113554.1.2.2"); - public static final Oid KRB5_NT_PRINCIPAL = createOID("1.2.840.113554.1.2.2.1"); - - // Options: - // - // Service principal name: if unset, use host/hostname - - private String servicePrincipalName; - - // Location of Kerberos key table; if unset use default - - private String keytabFile; - - // The on-going GSS context. - - private GSSContext ctxt; - - // Accept credentials - - private GSSCredential creds; - - // Original request data - - private String user; - private String service; - - // Identity from context - - private String identity; - - // Logging - - private Logger log = LoggerFactory.getLogger(getClass()); - - /** - * Handle the first authentication step. - * - * @param sess The server session - * @param user The user name from the request - * @param buff The request buffer - * - * @return True or false if the authentication succeeded, or <code>null</code> to continue further - * - * @throws Exception If something went wrong - */ - - public Boolean auth(ServerSession sess, String user, Buffer buff) throws Exception { - GSSAuthenticator auth = getAuthenticator(sess); - - this.user = user; - - // Get mechanism count from buffer and look for Kerberos 5. - - int num = buff.getInt(); - - for (int i = 0; i < num; i++) { - Oid oid = new Oid(buff.getBytes()); - - if (oid.equals(KRB5_MECH)) { - log.debug("UserAuthGSS: found Kerberos 5"); - - // Validate initial user before proceeding - - if (!auth.validateInitialUser(sess, user)) { - return Boolean.FALSE; - } - GSSManager mgr = auth.getGSSManager(); - GSSCredential creds = auth.getGSSCredential(mgr); - - if (creds == null) { - return Boolean.FALSE; + // Oids for the Kerberos 5 mechanism and principal + + public static final Oid KRB5_MECH = createOID("1.2.840.113554.1.2.2"); + public static final Oid KRB5_NT_PRINCIPAL = createOID("1.2.840.113554.1.2.2.1"); + + // Options: + // + // Service principal name: if unset, use host/hostname + + private String servicePrincipalName; + + // Location of Kerberos key table; if unset use default + + private String keytabFile; + + // The on-going GSS context. + + private GSSContext ctxt; + + // Accept credentials + + private GSSCredential creds; + + // Original request data + + private String user; + private String service; + + // Identity from context + + private String identity; + + // Logging + + private Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Handle the first authentication step. + * + * @param sess The server session + * @param user The user name from the request + * @param buff The request buffer + * @return True or false if the authentication succeeded, or <code>null</code> to continue further + * @throws Exception If something went wrong + */ + + public Boolean auth(ServerSession sess, String user, Buffer buff) throws Exception { + GSSAuthenticator auth = getAuthenticator(sess); + + this.user = user; + + // Get mechanism count from buffer and look for Kerberos 5. + + int num = buff.getInt(); + + for (int i = 0; i < num; i++) { + Oid oid = new Oid(buff.getBytes()); + + if (oid.equals(KRB5_MECH)) { + log.debug("UserAuthGSS: found Kerberos 5"); + + // Validate initial user before proceeding + + if (!auth.validateInitialUser(sess, user)) { + return Boolean.FALSE; + } + + GSSManager mgr = auth.getGSSManager(); + GSSCredential creds = auth.getGSSCredential(mgr); + + if (creds == null) { + return Boolean.FALSE; + } + + ctxt = mgr.createContext(creds); + + // Send the matching mechanism back to the client + + Buffer b = sess.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_INFO_REQUEST, 0); + byte[] out = oid.getDER(); + + b.putBytes(out); + sess.writePacket(b); + + return null; + } } - ctxt = mgr.createContext(creds); - - // Send the matching mechanism back to the client + // No matching mechanism found + + return Boolean.FALSE; + } - Buffer b = sess.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_INFO_REQUEST, 0); - byte [] out = oid.getDER(); + /** + * Set the service name from the original request. This may be required for MIC verification later. + * + * @param service The service name + */ - b.putBytes(out); - sess.writePacket(b); - - return null; - } + public void setServiceName(String service) { + this.service = service; } - - // No matching mechanism found - - return Boolean.FALSE; - } - - /** - * Set the service name from the original request. This may be required for MIC verification later. - * - * @param service The service name - */ - - public void setServiceName(String service) { - this.service = service; - } - - /** - * Check whether a particular message is handled here. - * - * @param msg The message - * - * @return <code>true</code> if the message is handled - */ - - public boolean handles(SshConstants.Message msg) { - return msg == SshConstants.Message.SSH_MSG_USERAUTH_INFO_RESPONSE || msg == SshConstants.Message.SSH_MSG_USERAUTH_GSSAPI_MIC && ctxt.isEstablished(); - } - - /** - * Handle another step in the authentication process. - * - * @param session the current ssh session - * @param buffer the request buffer containing parameters specific to this request - * - * @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication - * is not finished yet - * - * @throws Exception if the authentication fails - */ - - public Boolean next(ServerSession session, SshConstants.Message msg, Buffer buffer) throws Exception { - GSSAuthenticator auth = getAuthenticator(session); - - log.debug("In krb5.next: msg = " + msg); - - // If the context is established, this must be a MIC message - - if (ctxt.isEstablished()) { - - if (msg != SshConstants.Message.SSH_MSG_USERAUTH_GSSAPI_MIC) { - return Boolean.FALSE; - } - - // Make the MIC message so the token can be verified - - Buffer msgbuf = new Buffer(); - - msgbuf.putString(session.getSessionId()); - msgbuf.putByte(SshConstants.Message.SSH_MSG_USERAUTH_REQUEST.toByte()); - msgbuf.putString(user.getBytes("UTF-8")); - msgbuf.putString(service); - msgbuf.putString("gssapi-with-mic"); - - byte [] msgbytes = msgbuf.getCompactData(); - byte [] inmic = buffer.getBytes(); - - try { - ctxt.verifyMIC(inmic, 0, inmic.length, msgbytes, 0, msgbytes.length, new MessageProp(false)); - log.debug("MIC verified"); - return Boolean.TRUE; - } catch (GSSException e) { - log.info("GSS verification error: {}", e.toString()); - return Boolean.FALSE; - } - - } else { - - // Not established - new token to process - - byte [] tok = buffer.getBytes(); - byte [] out = ctxt.acceptSecContext(tok, 0, tok.length); - boolean established = ctxt.isEstablished(); - - // Validate identity if context is now established - - if (established && identity == null) { - identity = ctxt.getSrcName().toString(); - log.info("GSS identity is {}", identity); - - if (!auth.validateIdentity(session, identity)) { - return Boolean.FALSE; - } - } - - // Send return token if necessary - - if (out != null && out.length > 0) { - Buffer b = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_INFO_RESPONSE, 0); - - b.putBytes(out); - session.writePacket(b); - return null; - } else { - return Boolean.valueOf(established); - } + + /** + * Check whether a particular message is handled here. + * + * @param msg The message + * @return <code>true</code> if the message is handled + */ + + public boolean handles(SshConstants.Message msg) { + return msg == SshConstants.Message.SSH_MSG_USERAUTH_INFO_RESPONSE || msg == SshConstants.Message.SSH_MSG_USERAUTH_GSSAPI_MIC && ctxt.isEstablished(); } - } - - /** - * Get a user name which has been derived from the handshaking process, or the initial name if - * nothing has been found. - * - * @return The user name - */ - - public String getUserName() throws GSSException { - return identity; - } - - /** - * Free any system resources used by the module. - */ - - public void destroy() { - if (creds != null) { - try { - creds.dispose(); - } catch (GSSException e) { - // ignore - } - - if (ctxt != null) { - - try { - ctxt.dispose(); - } catch (GSSException e) { - // ignore + + /** + * Handle another step in the authentication process. + * + * @param session the current ssh session + * @param buffer the request buffer containing parameters specific to this request + * @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication + * is not finished yet + * @throws Exception if the authentication fails + */ + + public Boolean next(ServerSession session, SshConstants.Message msg, Buffer buffer) throws Exception { + GSSAuthenticator auth = getAuthenticator(session); + + log.debug("In krb5.next: msg = " + msg); + + // If the context is established, this must be a MIC message + + if (ctxt.isEstablished()) { + + if (msg != SshConstants.Message.SSH_MSG_USERAUTH_GSSAPI_MIC) { + return Boolean.FALSE; + } + + // Make the MIC message so the token can be verified + + Buffer msgbuf = new Buffer(); + + msgbuf.putString(session.getSessionId()); + msgbuf.putByte(SshConstants.Message.SSH_MSG_USERAUTH_REQUEST.toByte()); + msgbuf.putString(user.getBytes("UTF-8")); + msgbuf.putString(service); + msgbuf.putString("gssapi-with-mic"); + + byte[] msgbytes = msgbuf.getCompactData(); + byte[] inmic = buffer.getBytes(); + + try { + ctxt.verifyMIC(inmic, 0, inmic.length, msgbytes, 0, msgbytes.length, new MessageProp(false)); + log.debug("MIC verified"); + return Boolean.TRUE; + } catch (GSSException e) { + log.info("GSS verification error: {}", e.toString()); + return Boolean.FALSE; + } + + } else { + + // Not established - new token to process + + byte[] tok = buffer.getBytes(); + byte[] out = ctxt.acceptSecContext(tok, 0, tok.length); + boolean established = ctxt.isEstablished(); + + // Validate identity if context is now established + + if (established && identity == null) { + identity = ctxt.getSrcName().toString(); + log.info("GSS identity is {}", identity); + + if (!auth.validateIdentity(session, identity)) { + return Boolean.FALSE; + } + } + + // Send return token if necessary + + if (out != null && out.length > 0) { + Buffer b = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_INFO_RESPONSE, 0); + + b.putBytes(out); + session.writePacket(b); + return null; + } else { + return Boolean.valueOf(established); + } } - } } - } - - /** - * Utility to get the configured GSS authenticator for the server, throwing an exception if none is available. - * - * @param session The current session - * - * @return The GSS authenticator - * - * @throws Exception If no GSS authenticator is defined - */ - - private GSSAuthenticator getAuthenticator(ServerSession session) throws Exception { - GSSAuthenticator ga = session.getServerFactoryManager().getGSSAuthenticator(); - - if (ga == null) { - throw new Exception("No GSSAuthenticator configured"); - } else { - return ga; + + /** + * Get a user name which has been derived from the handshaking process, or the initial name if + * nothing has been found. + * + * @return The user name + */ + + public String getUserName() throws GSSException { + return identity; + } + + /** + * Free any system resources used by the module. + */ + + public void destroy() { + if (creds != null) { + try { + creds.dispose(); + } catch (GSSException e) { + // ignore + } + + if (ctxt != null) { + + try { + ctxt.dispose(); + } catch (GSSException e) { + // ignore + } + } + } } - } - - /** - * Utility to construct an Oid from a string, ignoring the annoying exception. - * - * @param rep The string form - * - * @return The Oid - */ - - private static Oid createOID(String rep) { - try { - return new Oid(rep); - } catch (GSSException e) { - // won't happen - return null; + + /** + * Utility to get the configured GSS authenticator for the server, throwing an exception if none is available. + * + * @param session The current session + * @return The GSS authenticator + * @throws Exception If no GSS authenticator is defined + */ + + private GSSAuthenticator getAuthenticator(ServerSession session) throws Exception { + GSSAuthenticator ga = session.getServerFactoryManager().getGSSAuthenticator(); + + if (ga == null) { + throw new Exception("No GSSAuthenticator configured"); + } else { + return ga; + } } - } - - /** - * Factory class. - */ - - public static class Factory implements NamedFactory<UserAuth> { - + /** - * Get the name of the authentication method. - * - * @return Tge name, always 'gssapi-with-mic' here. + * Utility to construct an Oid from a string, ignoring the annoying exception. + * + * @param rep The string form + * @return The Oid */ - - public String getName() { - return "gssapi-with-mic"; + + private static Oid createOID(String rep) { + try { + return new Oid(rep); + } catch (GSSException e) { + // won't happen + return null; + } } - + /** - * Create a new authenticator instance. - * - * @return The instance + * Factory class. */ - - public UserAuth create() { - return new UserAuthGSS(); + + public static class Factory implements NamedFactory<UserAuth> { + + /** + * Get the name of the authentication method. + * + * @return Tge name, always 'gssapi-with-mic' here. + */ + + public String getName() { + return "gssapi-with-mic"; + } + + /** + * Create a new authenticator instance. + * + * @return The instance + */ + + public UserAuth create() { + return new UserAuthGSS(); + } } - } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/34098dac/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java index f095ed7..d87fdd4 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java @@ -364,69 +364,69 @@ public class ServerSession extends AbstractSession { if (nbAuthRequests++ > maxAuthRequests) { throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Too may authentication failures"); } - - Boolean authed = null; - String username = null; + + Boolean authed = null; + String username = null; if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_REQUEST) { - username = buffer.getString(); - - String svcName = buffer.getString(); - String method = buffer.getString(); - - log.debug("Authenticating user '{}' with method '{}'", username, method); - NamedFactory<UserAuth> factory = NamedFactory.Utils.get(userAuthFactories, method); - if (factory != null) { - UserAuth auth = factory.create(); - try { - authed = auth.auth(this, username, buffer); - if (authed == null) { - // authentication is still ongoing - log.debug("Authentication not finished"); - - if (auth instanceof HandshakingUserAuth) { - currentAuth = (HandshakingUserAuth) auth; - - // GSSAPI needs the user name and service to verify the MIC - - currentAuth.setServiceName(svcName); + username = buffer.getString(); + + String svcName = buffer.getString(); + String method = buffer.getString(); + + log.debug("Authenticating user '{}' with method '{}'", username, method); + NamedFactory<UserAuth> factory = NamedFactory.Utils.get(userAuthFactories, method); + if (factory != null) { + UserAuth auth = factory.create(); + try { + authed = auth.auth(this, username, buffer); + if (authed == null) { + // authentication is still ongoing + log.debug("Authentication not finished"); + + if (auth instanceof HandshakingUserAuth) { + currentAuth = (HandshakingUserAuth) auth; + + // GSSAPI needs the user name and service to verify the MIC + + currentAuth.setServiceName(svcName); + } + return; + } else { + log.debug(authed ? "Authentication succeeded" : "Authentication failed"); + } + } catch (Exception e) { + // Continue + authed = false; + log.debug("Authentication failed: {}", e.getMessage()); } - return; - } else { - log.debug(authed ? "Authentication succeeded" : "Authentication failed"); - } - } catch (Exception e) { - // Continue - authed = false; - log.debug("Authentication failed: {}", e.getMessage()); + + } else { + log.debug("Unsupported authentication method '{}'", method); } - - } else { - log.debug("Unsupported authentication method '{}'", method); - } } else { - try { - authed = currentAuth.next(this, cmd, buffer); - - if (authed == null) { - // authentication is still ongoing - log.debug("Authentication still not finished"); - return; - } else if (authed.booleanValue()) { - username = currentAuth.getUserName(); + try { + authed = currentAuth.next(this, cmd, buffer); + + if (authed == null) { + // authentication is still ongoing + log.debug("Authentication still not finished"); + return; + } else if (authed.booleanValue()) { + username = currentAuth.getUserName(); + } + } catch (Exception e) { + // failed + authed = false; + log.debug("Authentication next failed: {}", e.getMessage()); } - } catch (Exception e) { - // failed - authed = false; - log.debug("Authentication next failed: {}", e.getMessage()); - } } // No more handshakes now - clean up if necessary - + if (currentAuth != null) { - currentAuth.destroy(); - currentAuth = null; + currentAuth.destroy(); + currentAuth = null; } if (authed != null && authed) {
