LCOV - code coverage report
Current view: top level - src/esys/repo/libssh2 - ssh_libssh2.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 47 97 48.5 %
Date: 2026-08-01 10:43:40 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/libssh2/ssh_libssh2.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2021-2022 Michel Gillet
       9             :  * Distributed under the MIT License.
      10             :  * (See accompanying file LICENSE.txt or
      11             :  * copy at https://opensource.org/licenses/MIT)
      12             :  *
      13             :  * __legal_e__
      14             :  * \endcond
      15             :  *
      16             :  */
      17             : 
      18             : #include "esys/repo/esysrepo_prec.h"
      19             : #include "esys/repo/libssh2/ssh.h"
      20             : #include "esys/repo/libssh2/sshimpl.h"
      21             : 
      22             : #include <boost/filesystem.hpp>
      23             : 
      24             : #include <fstream>
      25             : #include <sstream>
      26             : #include <cstdlib>
      27             : 
      28             : namespace esys::repo::libssh2
      29             : {
      30             : 
      31             : std::string SSH::s_dflt_agent_identity_path;
      32             : 
      33           1 : void SSH::set_dflt_agent_identity_path(const std::string &agent_identity_path)
      34             : {
      35           1 :     s_dflt_agent_identity_path = agent_identity_path;
      36           1 : }
      37             : 
      38         331 : const std::string &SSH::get_dflt_agent_identity_path()
      39             : {
      40         331 :     return s_dflt_agent_identity_path;
      41             : }
      42             : 
      43         203 : SSH::SSH()
      44         203 :     : SSHBase()
      45             : {
      46         203 :     m_impl = std::make_unique<SSHImpl>(this);
      47         203 : }
      48             : 
      49         203 : SSH::~SSH() = default;
      50             : 
      51         193 : bool SSH::is_agent_present()
      52             : {
      53         193 :     check_for_custom_agent();
      54             : 
      55         193 :     if (_get_agent_present() == AgentPresent::NOT_CHECKED)
      56             :     {
      57         139 :         bool present = m_impl->is_agent_present();
      58         139 :         if (present)
      59         139 :             _set_agent_present(AgentPresent::PRESENT);
      60             :         else
      61           0 :             _set_agent_present(AgentPresent::NOT_PRESENT);
      62             :     }
      63         193 :     return (_get_agent_present() == AgentPresent::PRESENT);
      64             : }
      65             : 
      66         193 : void SSH::check_for_custom_agent(bool force_check)
      67             : {
      68         193 :     static int s_run_count = 0;
      69             : 
      70         193 :     if (s_run_count > 0) return;
      71             : 
      72           1 :     ++s_run_count;
      73             : 
      74           1 :     bool do_check = true;
      75             : #ifndef ESYSREPO_SNAP_BUILD
      76           1 :     do_check = false;
      77             : #endif
      78             : 
      79           1 :     if (do_check) debug(0, "Snap detected");
      80             : 
      81           1 :     char *ssh_auth_sock_c = getenv("SSH_AUTH_SOCK");
      82           1 :     std::string ssh_auth_sock = ssh_auth_sock_c ? ssh_auth_sock_c : "";
      83             : 
      84           1 :     if (ssh_auth_sock.size() != 0)
      85             :     {
      86           1 :         std::ostringstream oss;
      87             : 
      88           1 :         oss << "SSH_AUTH_SOCK = '" << ssh_auth_sock << "'";
      89           1 :         debug(0, oss.str());
      90           1 :     }
      91             :     else
      92             :     {
      93           0 :         debug(0, "SSH_AUTH_SOCK is not set");
      94           0 :         return;
      95             :     }
      96             : 
      97           1 :     if (!do_check && !force_check)
      98             :     {
      99           1 :         std::ostringstream oss;
     100             : 
     101           1 :         oss << "Set set_agent_identity_path to '" << ssh_auth_sock << "'";
     102           1 :         debug(0, oss.str());
     103           1 :         set_agent_identity_path(ssh_auth_sock.c_str());
     104           1 :         return;
     105           1 :     }
     106             : 
     107           0 :     char *home_c = std::getenv("HOME");
     108           0 :     char *snap_real_home_c = std::getenv("SNAP_REAL_HOME");
     109             : 
     110           0 :     boost::filesystem::path home = home_c;
     111           0 :     boost::filesystem::path snap_real_home = snap_real_home_c;
     112             : 
     113           0 :     std::ostringstream oss;
     114             : 
     115           0 :     oss << "SNAP_REAL_HOME = '" << snap_real_home << "'";
     116           0 :     debug(0, oss.str());
     117             : 
     118           0 :     if (ssh_auth_sock.find(snap_real_home.string()) == 0)
     119             :     {
     120           0 :         debug(0, "Nothing to do.");
     121           0 :         return;
     122             :     }
     123             : 
     124             :     // SSH_AUTH_SOCK points to a file that can be accessed by a snap application
     125           0 :     boost::filesystem::path esysrepo_dir = snap_real_home;
     126           0 :     boost::filesystem::path new_ssh_auth_sock;
     127           0 :     esysrepo_dir /= "_esysrepo";
     128           0 :     new_ssh_auth_sock = esysrepo_dir / ssh_auth_sock;
     129             : 
     130           0 :     if (boost::filesystem::exists(new_ssh_auth_sock))
     131             :     {
     132           0 :         std::ostringstream oss;
     133             : 
     134           0 :         oss << "Set set_agent_identity_path to '" << new_ssh_auth_sock.string() << "'";
     135           0 :         debug(0, oss.str());
     136             : 
     137           0 :         set_agent_identity_path(new_ssh_auth_sock.string());
     138           0 :         return;
     139           0 :     }
     140             : 
     141           0 :     oss.str("");
     142             : 
     143           0 :     oss << "This application was installed from a snap package." << std::endl;
     144           0 :     oss << "So it can't access the /tmp folder. When using an ssh agent or" << std::endl;
     145           0 :     oss << "using agent forwarding, required files are written to the /tmp." << std::endl;
     146           0 :     oss << "Currently, the only way around this is to mount the /tmp folder" << std::endl;
     147           0 :     oss << "in your home folder." << std::endl;
     148           0 :     oss << std::endl;
     149           0 :     oss << "To mount the /tmp folder:" << std::endl;
     150             : 
     151           0 :     boost::filesystem::path path = esysrepo_dir / "tmp";
     152           0 :     boost::filesystem::path tmp_path = path;
     153             : 
     154           0 :     if (!boost::filesystem::exists(path))
     155             :     {
     156           0 :         boost::filesystem::create_directories(path);
     157             :     }
     158             : 
     159           0 :     path = snap_real_home / "bin";
     160           0 :     if (!boost::filesystem::exists(path))
     161             :     {
     162           0 :         boost::filesystem::create_directories(path);
     163             :     }
     164             : 
     165           0 :     path /= "esysrepo_mount_tmp.sh";
     166             : 
     167           0 :     oss << "sudo " << path.string() << std::endl;
     168             : 
     169           0 :     std::ofstream ofs(path.string().c_str(), std::ios_base::out | std::ios_base::trunc);
     170             : 
     171           0 :     ofs << "#!/usr/bin/env sh" << std::endl;
     172           0 :     ofs << std::endl;
     173           0 :     ofs << "# This file was generated by esysrepo, so don't modify it." << std::endl;
     174           0 :     ofs << std::endl;
     175           0 :     ofs << "sudo mount --bind /tmp " << tmp_path.string() << std::endl;
     176           0 :     ofs.close();
     177             : 
     178           0 :     boost::filesystem::permissions(path, boost::filesystem::owner_exe | boost::filesystem::owner_read
     179             :                                              | boost::filesystem::owner_write);
     180           0 :     warn(oss.str());
     181         194 : }
     182             : 
     183           1 : void SSH::set_agent_identity_path(const std::string &agent_identity_path)
     184             : {
     185           1 :     SSHBase::set_agent_identity_path(agent_identity_path);
     186             : 
     187           1 :     if (get_dflt_agent_identity_path().empty()) set_dflt_agent_identity_path(agent_identity_path);
     188           1 : }
     189             : 
     190         278 : const std::string &SSH::get_agent_identity_path() const
     191             : {
     192         278 :     if (!SSHBase::get_agent_identity_path().empty()) return SSHBase::get_agent_identity_path();
     193             : 
     194         138 :     m_agent_identity_path = get_dflt_agent_identity_path();
     195             : 
     196         138 :     return m_agent_identity_path;
     197             : }
     198             : 
     199             : } // namespace esys::repo::libssh2

Generated by: LCOV version 1.14