/**
   * Detects the current-user-principal for a given WebDavResource. At first, /.well-known/ is
   * tried. Only if no current-user-principal can be detected for the .well-known location, the
   * given location of the resource is tried.
   *
   * @param serverInfo Location that will be queried
   * @param serviceName Well-known service name ("carddav", "caldav")
   * @return WebDavResource of current-user-principal for the given service, or null if it can't be
   *     found
   *     <p>TODO: If a TXT record is given, always use it instead of trying .well-known first
   */
  WebDavResource getCurrentUserPrincipal(ServerInfo serverInfo, String serviceName)
      throws URISyntaxException, IOException, NotAuthorizedException {
    URI initialURL = getInitialContextURL(serverInfo, serviceName);
    if (initialURL != null) {
      Log.i(
          TAG,
          "Looking up principal URL for service "
              + serviceName
              + "; initial context: "
              + initialURL);

      // determine base URL (host name and initial context path)
      WebDavResource base =
          new WebDavResource(
              httpClient,
              initialURL,
              serverInfo.getUserName(),
              serverInfo.getPassword(),
              serverInfo.isAuthPreemptive());

      // look for well-known service (RFC 5785)
      try {
        WebDavResource wellKnown = new WebDavResource(base, "/.well-known/" + serviceName);
        wellKnown.propfind(Mode.CURRENT_USER_PRINCIPAL);
        if (wellKnown.getProperties().getCurrentUserPrincipal() != null) {
          URI principal = wellKnown.getProperties().getCurrentUserPrincipal();
          Log.i(TAG, "Principal URL found from Well-Known URI: " + principal);
          return new WebDavResource(wellKnown, principal);
        }
      } catch (NotAuthorizedException e) {
        Log.w(TAG, "Not authorized for well-known " + serviceName + " service detection", e);
        throw e;
      } catch (URISyntaxException e) {
        Log.e(
            TAG,
            "Well-known" + serviceName + " service detection failed because of invalid URIs",
            e);
      } catch (HttpException e) {
        Log.d(TAG, "Well-known " + serviceName + " service detection failed with HTTP error", e);
      } catch (DavException e) {
        Log.w(
            TAG,
            "Well-known " + serviceName + " service detection failed with unexpected DAV response",
            e);
      } catch (IOException e) {
        Log.e(TAG, "Well-known " + serviceName + " service detection failed with I/O error", e);
      }

      // fall back to user-given initial context path
      Log.d(TAG, "Well-known service detection failed, trying initial context path " + initialURL);
      try {
        base.propfind(Mode.CURRENT_USER_PRINCIPAL);
        if (base.getProperties().getCurrentUserPrincipal() != null) {
          URI principal = base.getProperties().getCurrentUserPrincipal();
          Log.i(TAG, "Principal URL found from initial context path: " + principal);
          return new WebDavResource(base, principal);
        }
      } catch (NotAuthorizedException e) {
        Log.e(TAG, "Not authorized for querying principal", e);
        throw e;
      } catch (HttpException e) {
        Log.e(TAG, "HTTP error when querying principal", e);
      } catch (DavException e) {
        Log.e(TAG, "DAV error when querying principal", e);
      }

      Log.i(
          TAG,
          "Couldn't find current-user-principal for service "
              + serviceName
              + ", assuming initial context path is principal path");
      return base;
    }
    return null;
  }
예제 #2
0
  /**
   * This will not reuse any session, it will create the session and close it at the end
   *
   * @param commandInfo Encapsulated information about command. E.g :- executable name parameters
   *     etc ...
   * @param serverInfo The SSHing server information.
   * @param authenticationInfo Security data needs to be communicated with remote server.
   * @param commandOutput The output of the command.
   * @param configReader configuration required for ssh/gshissh connection
   * @throws SSHApiException throw exception when error occurs
   */
  public static void executeCommand(
      CommandInfo commandInfo,
      ServerInfo serverInfo,
      AuthenticationInfo authenticationInfo,
      CommandOutput commandOutput,
      ConfigReader configReader)
      throws SSHApiException {

    if (authenticationInfo instanceof GSIAuthenticationInfo) {
      System.setProperty(
          X509_CERT_DIR,
          (String)
              ((GSIAuthenticationInfo) authenticationInfo).getProperties().get("X509_CERT_DIR"));
    }

    JSch jsch = new ExtendedJSch();

    log.debug(
        "Connecting to server - "
            + serverInfo.getHost()
            + ":"
            + serverInfo.getPort()
            + " with user name - "
            + serverInfo.getUserName());

    Session session;

    try {
      session =
          jsch.getSession(serverInfo.getUserName(), serverInfo.getHost(), serverInfo.getPort());
    } catch (JSchException e) {
      throw new SSHApiException(
          "An exception occurred while creating SSH session."
              + "Connecting server - "
              + serverInfo.getHost()
              + ":"
              + serverInfo.getPort()
              + " connecting user name - "
              + serverInfo.getUserName(),
          e);
    }

    java.util.Properties config = configReader.getProperties();
    session.setConfig(config);

    // =============================================================
    // Handling vanilla SSH pieces
    // =============================================================
    if (authenticationInfo instanceof SSHPasswordAuthentication) {
      String password =
          ((SSHPasswordAuthentication) authenticationInfo)
              .getPassword(serverInfo.getUserName(), serverInfo.getHost());

      session.setUserInfo(new SSHAPIUIKeyboardInteractive(password));

      // TODO figure out why we need to set password to session
      session.setPassword(password);

    } else if (authenticationInfo instanceof SSHPublicKeyFileAuthentication) {
      SSHPublicKeyFileAuthentication sshPublicKeyFileAuthentication =
          (SSHPublicKeyFileAuthentication) authenticationInfo;

      String privateKeyFile =
          sshPublicKeyFileAuthentication.getPrivateKeyFile(
              serverInfo.getUserName(), serverInfo.getHost());

      logDebug("The private key file for vanilla SSH " + privateKeyFile);

      String publicKeyFile =
          sshPublicKeyFileAuthentication.getPrivateKeyFile(
              serverInfo.getUserName(), serverInfo.getHost());

      logDebug("The public key file for vanilla SSH " + publicKeyFile);

      Identity identityFile;

      try {
        identityFile = GSISSHIdentityFile.newInstance(privateKeyFile, null, jsch);
      } catch (JSchException e) {
        throw new SSHApiException(
            "An exception occurred while initializing keys using files. "
                + "(private key and public key)."
                + "Connecting server - "
                + serverInfo.getHost()
                + ":"
                + serverInfo.getPort()
                + " connecting user name - "
                + serverInfo.getUserName()
                + " private key file - "
                + privateKeyFile
                + ", public key file - "
                + publicKeyFile,
            e);
      }

      // Add identity to identity repository
      GSISSHIdentityRepository identityRepository = new GSISSHIdentityRepository(jsch);
      identityRepository.add(identityFile);

      // Set repository to session
      session.setIdentityRepository(identityRepository);

      // Set the user info
      SSHKeyPasswordHandler sshKeyPasswordHandler =
          new SSHKeyPasswordHandler((SSHKeyAuthentication) authenticationInfo);

      session.setUserInfo(sshKeyPasswordHandler);

    } else if (authenticationInfo instanceof SSHPublicKeyAuthentication) {

      SSHPublicKeyAuthentication sshPublicKeyAuthentication =
          (SSHPublicKeyAuthentication) authenticationInfo;

      Identity identityFile;

      try {
        String name = serverInfo.getUserName() + "_" + serverInfo.getHost();
        identityFile =
            GSISSHIdentityFile.newInstance(
                name,
                sshPublicKeyAuthentication.getPrivateKey(
                    serverInfo.getUserName(), serverInfo.getHost()),
                sshPublicKeyAuthentication.getPublicKey(
                    serverInfo.getUserName(), serverInfo.getHost()),
                jsch);
      } catch (JSchException e) {
        throw new SSHApiException(
            "An exception occurred while initializing keys using byte arrays. "
                + "(private key and public key)."
                + "Connecting server - "
                + serverInfo.getHost()
                + ":"
                + serverInfo.getPort()
                + " connecting user name - "
                + serverInfo.getUserName(),
            e);
      }

      // Add identity to identity repository
      GSISSHIdentityRepository identityRepository = new GSISSHIdentityRepository(jsch);
      identityRepository.add(identityFile);

      // Set repository to session
      session.setIdentityRepository(identityRepository);

      // Set the user info
      SSHKeyPasswordHandler sshKeyPasswordHandler =
          new SSHKeyPasswordHandler((SSHKeyAuthentication) authenticationInfo);

      session.setUserInfo(sshKeyPasswordHandler);
    }

    // Not a good way, but we dont have any choice
    if (session instanceof ExtendedSession) {
      if (authenticationInfo instanceof GSIAuthenticationInfo) {
        ((ExtendedSession) session)
            .setAuthenticationInfo((GSIAuthenticationInfo) authenticationInfo);
      }
    }

    try {
      session.connect();
    } catch (JSchException e) {
      throw new SSHApiException(
          "An exception occurred while connecting to server."
              + "Connecting server - "
              + serverInfo.getHost()
              + ":"
              + serverInfo.getPort()
              + " connecting user name - "
              + serverInfo.getUserName(),
          e);
    }

    String command = commandInfo.getCommand();

    Channel channel;
    try {
      channel = session.openChannel("exec");
      ((ChannelExec) channel).setCommand(command);
    } catch (JSchException e) {
      session.disconnect();

      throw new SSHApiException(
          "Unable to execute command - "
              + command
              + " on server - "
              + serverInfo.getHost()
              + ":"
              + serverInfo.getPort()
              + " connecting user name - "
              + serverInfo.getUserName(),
          e);
    }

    channel.setInputStream(null);
    ((ChannelExec) channel).setErrStream(commandOutput.getStandardError());

    try {
      channel.connect();
    } catch (JSchException e) {

      channel.disconnect();
      session.disconnect();

      throw new SSHApiException(
          "Unable to retrieve command output. Command - "
              + command
              + " on server - "
              + serverInfo.getHost()
              + ":"
              + serverInfo.getPort()
              + " connecting user name - "
              + serverInfo.getUserName(),
          e);
    }

    commandOutput.onOutput(channel);

    channel.disconnect();
    session.disconnect();
  }