JGitServerKeyVerifier.java

  1. /*
  2.  * Copyright (C) 2019 Thomas Wolf <thomas.wolf@paranor.ch> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.internal.transport.sshd;

  11. import static org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile.flag;

  12. import java.net.InetSocketAddress;
  13. import java.net.SocketAddress;
  14. import java.security.PublicKey;
  15. import java.util.Collections;
  16. import java.util.List;
  17. import java.util.Locale;

  18. import org.apache.sshd.client.config.hosts.HostConfigEntry;
  19. import org.apache.sshd.client.config.hosts.KnownHostHashValue;
  20. import org.apache.sshd.client.keyverifier.ServerKeyVerifier;
  21. import org.apache.sshd.client.session.ClientSession;
  22. import org.apache.sshd.common.util.net.SshdSocketAddress;
  23. import org.eclipse.jgit.annotations.NonNull;
  24. import org.eclipse.jgit.transport.CredentialsProvider;
  25. import org.eclipse.jgit.transport.SshConstants;
  26. import org.eclipse.jgit.transport.sshd.ServerKeyDatabase;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;

  29. /**
  30.  * A bridge between the {@link ServerKeyVerifier} from Apache MINA sshd and our
  31.  * {@link ServerKeyDatabase}.
  32.  */
  33. public class JGitServerKeyVerifier
  34.         implements ServerKeyVerifier, ServerKeyLookup {

  35.     private static final Logger LOG = LoggerFactory
  36.             .getLogger(JGitServerKeyVerifier.class);

  37.     private final @NonNull ServerKeyDatabase database;

  38.     /**
  39.      * Creates a new {@link JGitServerKeyVerifier} using the given
  40.      * {@link ServerKeyDatabase}.
  41.      *
  42.      * @param database
  43.      *            to use
  44.      */
  45.     public JGitServerKeyVerifier(@NonNull ServerKeyDatabase database) {
  46.         this.database = database;
  47.     }

  48.     @Override
  49.     public List<PublicKey> lookup(ClientSession session,
  50.             SocketAddress remoteAddress) {
  51.         if (!(session instanceof JGitClientSession)) {
  52.             LOG.warn("Internal error: wrong session kind: " //$NON-NLS-1$
  53.                     + session.getClass().getName());
  54.             return Collections.emptyList();
  55.         }
  56.         if (!(remoteAddress instanceof InetSocketAddress)) {
  57.             return Collections.emptyList();
  58.         }
  59.         SessionConfig config = new SessionConfig((JGitClientSession) session);
  60.         SshdSocketAddress connectAddress = SshdSocketAddress
  61.                 .toSshdSocketAddress(session.getConnectAddress());
  62.         String connect = KnownHostHashValue.createHostPattern(
  63.                 connectAddress.getHostName(), connectAddress.getPort());
  64.         return database.lookup(connect, (InetSocketAddress) remoteAddress,
  65.                 config);
  66.     }

  67.     @Override
  68.     public boolean verifyServerKey(ClientSession session,
  69.             SocketAddress remoteAddress, PublicKey serverKey) {
  70.         if (!(session instanceof JGitClientSession)) {
  71.             LOG.warn("Internal error: wrong session kind: " //$NON-NLS-1$
  72.                     + session.getClass().getName());
  73.             return false;
  74.         }
  75.         if (!(remoteAddress instanceof InetSocketAddress)) {
  76.             return false;
  77.         }
  78.         SessionConfig config = new SessionConfig((JGitClientSession) session);
  79.         SshdSocketAddress connectAddress = SshdSocketAddress
  80.                 .toSshdSocketAddress(session.getConnectAddress());
  81.         String connect = KnownHostHashValue.createHostPattern(
  82.                 connectAddress.getHostName(), connectAddress.getPort());
  83.         CredentialsProvider provider = ((JGitClientSession) session)
  84.                 .getCredentialsProvider();
  85.         return database.accept(connect, (InetSocketAddress) remoteAddress,
  86.                 serverKey, config, provider);
  87.     }

  88.     private static class SessionConfig
  89.             implements ServerKeyDatabase.Configuration {

  90.         private final JGitClientSession session;

  91.         public SessionConfig(JGitClientSession session) {
  92.             this.session = session;
  93.         }

  94.         private List<String> get(String key) {
  95.             HostConfigEntry entry = session.getHostConfigEntry();
  96.             if (entry instanceof JGitHostConfigEntry) {
  97.                 // Always true!
  98.                 return ((JGitHostConfigEntry) entry).getMultiValuedOptions()
  99.                         .get(key);
  100.             }
  101.             return Collections.emptyList();
  102.         }

  103.         @Override
  104.         public List<String> getUserKnownHostsFiles() {
  105.             return get(SshConstants.USER_KNOWN_HOSTS_FILE);
  106.         }

  107.         @Override
  108.         public List<String> getGlobalKnownHostsFiles() {
  109.             return get(SshConstants.GLOBAL_KNOWN_HOSTS_FILE);
  110.         }

  111.         @Override
  112.         public StrictHostKeyChecking getStrictHostKeyChecking() {
  113.             HostConfigEntry entry = session.getHostConfigEntry();
  114.             String value = entry
  115.                     .getProperty(SshConstants.STRICT_HOST_KEY_CHECKING, "ask"); //$NON-NLS-1$
  116.             switch (value.toLowerCase(Locale.ROOT)) {
  117.             case SshConstants.YES:
  118.             case SshConstants.ON:
  119.                 return StrictHostKeyChecking.REQUIRE_MATCH;
  120.             case SshConstants.NO:
  121.             case SshConstants.OFF:
  122.                 return StrictHostKeyChecking.ACCEPT_ANY;
  123.             case "accept-new": //$NON-NLS-1$
  124.                 return StrictHostKeyChecking.ACCEPT_NEW;
  125.             default:
  126.                 return StrictHostKeyChecking.ASK;
  127.             }
  128.         }

  129.         @Override
  130.         public boolean getHashKnownHosts() {
  131.             HostConfigEntry entry = session.getHostConfigEntry();
  132.             return flag(entry.getProperty(SshConstants.HASH_KNOWN_HOSTS));
  133.         }

  134.         @Override
  135.         public String getUsername() {
  136.             return session.getUsername();
  137.         }
  138.     }
  139. }