org.apache.sshd.client.auth.hostbased.UserAuthHostBased Maven / Gradle / Ivy
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.sshd.client.auth.hostbased;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.sshd.client.auth.AbstractUserAuth;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.signature.Signature;
import org.apache.sshd.common.signature.SignatureFactoriesManager;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.common.util.net.SshdSocketAddress;
/**
* @author Apache MINA SSHD Project
*/
public class UserAuthHostBased extends AbstractUserAuth implements SignatureFactoriesManager {
public static final String NAME = UserAuthHostBasedFactory.NAME;
protected Iterator extends Map.Entry>> keys;
protected Map.Entry> keyInfo;
protected final HostKeyIdentityProvider clientHostKeys;
private List> factories;
private String clientUsername;
private String clientHostname;
public UserAuthHostBased(HostKeyIdentityProvider clientHostKeys) {
super(NAME);
this.clientHostKeys = clientHostKeys; // OK if null
}
@Override
public void init(ClientSession session, String service) throws Exception {
super.init(session, service);
keys = HostKeyIdentityProvider.iteratorOf(session, clientHostKeys); // in case multiple calls to the method
}
@Override
public List> getSignatureFactories() {
return factories;
}
@Override
public void setSignatureFactories(List> factories) {
this.factories = factories;
}
public String getClientUsername() {
return clientUsername;
}
public void setClientUsername(String clientUsername) {
this.clientUsername = clientUsername;
}
public String getClientHostname() {
return clientHostname;
}
public void setClientHostname(String clientHostname) {
this.clientHostname = clientHostname;
}
@Override
protected boolean sendAuthDataRequest(ClientSession session, String service) throws Exception {
String name = getName();
boolean debugEnabled = log.isDebugEnabled();
String clientUsername = resolveClientUsername(session);
String clientHostname = resolveClientHostname(session);
HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
keyInfo = ((keys != null) && keys.hasNext()) ? keys.next() : null;
if (keyInfo == null) {
if (debugEnabled) {
log.debug("sendAuthDataRequest({})[{}][{}] no more keys to send", session, service, name);
}
if (reporter != null) {
reporter.signalAuthenticationExhausted(session, service, clientUsername, clientHostname);
}
return false;
}
KeyPair kp = keyInfo.getKey();
PublicKey pub = kp.getPublic();
String keyType = KeyUtils.getKeyType(pub);
if (log.isTraceEnabled()) {
log.trace("sendAuthDataRequest({})[{}][{}] current key details: type={}, fingerprint={}",
session, service, name, keyType, KeyUtils.getFingerPrint(pub));
}
Collection> factories = ValidateUtils.checkNotNullAndNotEmpty(
SignatureFactoriesManager.resolveSignatureFactories(this, session),
"No signature factories for session=%s",
session);
Signature verifier = ValidateUtils.checkNotNull(
NamedFactory.create(factories, keyType),
"No signer could be located for key type=%s",
keyType);
byte[] id = session.getSessionId();
String username = session.getUsername();
if (debugEnabled) {
log.debug("sendAuthDataRequest({})[{}][{}] client={}@{}",
session, service, name, clientUsername, clientHostname);
}
int length = id.length + username.length() + service.length() + clientUsername.length() + clientHostname.length()
+ keyType.length() + ByteArrayBuffer.DEFAULT_SIZE + Long.SIZE;
Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST, length);
buffer.clear();
buffer.putRawPublicKey(pub);
Collection certs = keyInfo.getValue();
if (GenericUtils.size(certs) > 0) {
for (X509Certificate c : certs) {
// TODO make sure this yields DER encoding
buffer.putRawBytes(c.getEncoded());
}
}
verifier.initSigner(session, kp.getPrivate());
byte[] keyBytes = buffer.getCompactData();
buffer = session.prepareBuffer(
SshConstants.SSH_MSG_USERAUTH_REQUEST, BufferUtils.clear(buffer));
buffer.putString(username);
buffer.putString(service);
buffer.putString(name);
buffer.putString(keyType);
buffer.putBytes(keyBytes);
buffer.putString(clientHostname);
buffer.putString(clientUsername);
byte[] signature = appendSignature(
session, service, keyType, pub, keyBytes,
clientHostname, clientUsername, verifier, buffer);
if (reporter != null) {
reporter.signalAuthenticationAttempt(
session, service, kp, clientHostname, clientUsername, signature);
}
session.writePacket(buffer);
return true;
}
@SuppressWarnings("checkstyle:ParameterNumber")
protected byte[] appendSignature(
ClientSession session, String service,
String keyType, PublicKey key, byte[] keyBytes,
String clientHostname, String clientUsername,
Signature verifier, Buffer buffer)
throws Exception {
byte[] id = session.getSessionId();
String username = session.getUsername();
String name = getName();
int length = id.length + username.length() + service.length() + name.length() + keyType.length() + keyBytes.length
+ clientHostname.length() + clientUsername.length() + ByteArrayBuffer.DEFAULT_SIZE + Long.SIZE;
Buffer bs = new ByteArrayBuffer(length, false);
bs.putBytes(id);
bs.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
bs.putString(username);
bs.putString(service);
bs.putString(name);
bs.putString(keyType);
bs.putBytes(keyBytes);
bs.putString(clientHostname);
bs.putString(clientUsername);
verifier.update(session, bs.array(), bs.rpos(), bs.available());
byte[] signature = verifier.sign(session);
if (log.isTraceEnabled()) {
log.trace("appendSignature({})[{}][{}] type={}, fingerprint={}, client={}@{}: signature={}",
session, service, name, keyType, KeyUtils.getFingerPrint(key),
clientUsername, clientHostname, BufferUtils.toHex(signature));
}
bs.clear();
bs.putString(keyType);
bs.putBytes(signature);
buffer.putBytes(bs.array(), bs.rpos(), bs.available());
return signature;
}
@Override
protected boolean processAuthDataRequest(
ClientSession session, String service, Buffer buffer)
throws Exception {
int cmd = buffer.getUByte();
throw new IllegalStateException("processAuthDataRequest(" + session + ")[" + service + "]"
+ " received unknown packet: cmd=" + SshConstants.getCommandMessageName(cmd));
}
@Override
public void signalAuthMethodSuccess(ClientSession session, String service, Buffer buffer) throws Exception {
HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
if (reporter != null) {
reporter.signalAuthenticationSuccess(
session, service, (keyInfo == null) ? null : keyInfo.getKey(),
resolveClientHostname(session), resolveClientUsername(session));
}
}
@Override
public void signalAuthMethodFailure(
ClientSession session, String service, boolean partial, List serverMethods, Buffer buffer)
throws Exception {
HostBasedAuthenticationReporter reporter = session.getHostBasedAuthenticationReporter();
if (reporter != null) {
reporter.signalAuthenticationFailure(
session, service, (keyInfo == null) ? null : keyInfo.getKey(),
resolveClientHostname(session), resolveClientUsername(session),
partial, serverMethods);
}
}
protected String resolveClientUsername(ClientSession session) {
String value = getClientUsername();
return GenericUtils.isEmpty(value) ? OsUtils.getCurrentUser() : value;
}
protected String resolveClientHostname(ClientSession session) {
String value = getClientHostname();
if (GenericUtils.isEmpty(value)) {
value = SshdSocketAddress.toAddressString(
SshdSocketAddress.getFirstExternalNetwork4Address());
}
return GenericUtils.isEmpty(value) ? SshdSocketAddress.LOCALHOST_IPV4 : value;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy