diff --git a/recipes/openssh/all/conandata.yml b/recipes/openssh/all/conandata.yml new file mode 100644 index 0000000000000..7660d89300c4a --- /dev/null +++ b/recipes/openssh/all/conandata.yml @@ -0,0 +1,12 @@ +sources: + "9.1p1": + url: "https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.1p1.tar.gz" + sha256: "19f85009c7e3e23787f0236fbb1578392ab4d4bf9f8ec5fe6bc1cd7e8bfdd288" + "8.1p1": + url: "https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.1p1.tar.gz" + sha256: "02f5dbef3835d0753556f973cd57b4c19b6b1f6cd24c03445e23ac77ca1b93ff" +patches: + "9.1p1-neutrino-7.0": + - patch_file: "patches/pselect_timeout.patch" + patch_description: "Faulty pselect function workaround" + patch_type: "portability" diff --git a/recipes/openssh/all/conanfile.py b/recipes/openssh/all/conanfile.py new file mode 100644 index 0000000000000..d318486719ba7 --- /dev/null +++ b/recipes/openssh/all/conanfile.py @@ -0,0 +1,124 @@ +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.build import cross_building +from conan.tools.env import Environment, VirtualBuildEnv, VirtualRunEnv +from conan.tools.files import patch, copy, get, rm, rmdir +from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps +from conan.tools.layout import basic_layout +import os + + +required_conan_version = ">=1.54.0" + +class PackageConan(ConanFile): + name = "openssh" + description = "The OpenSSH (portable) suite of secure connectivity tools" + license = "BSD" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/openssh/openssh-portable" + topics = ("security", "cryptography", "login", "keychain", "file-sharing") + package_type = "application" + settings = "os", "arch", "compiler", "build_type" + options = { + "with_openssl": [True, False], + "with_pam": [True, False], + "with_sandbox": ["auto", "no", "capsicum", "darwin", "rlimit", "seccomp_filter", "systrace", "pledge"] + } + default_options = { + "with_openssl": True, + "with_pam": False, + "with_sandbox": "auto" + } + + def _patch_sources(self): + print("patching for {}-{}-{}".format(self.version, str(self.settings.os).lower(), self.settings.get_safe("os.version"))) + + # general patches + for p in self.conan_data.get("patches", {}).get(self.version, []): + print(f"patching general files: {p['patch_file']}") + patch(self, **p, base_path=self.source_folder) + + # os specific patches + for p in self.conan_data.get("patches", {}).get("{}-{}".format(self.version, str(self.settings.os).lower()), []): + print(f"patching os specific files: {p['patch_file']}") + patch(self, **p, base_path=self.source_folder) + + # os version specific patches + for p in self.conan_data.get("patches", {}).get("{}-{}-{}".format(self.version, str(self.settings.os).lower(), self.settings.get_safe("os.version")), []): + print(f"patching os version specific: {p['patch_file']}") + patch(self, **p, base_path=self.source_folder) + + def package_id(self): + del self.info.settings.compiler + del self.info.settings.build_type + + def export_sources(self): + copy(self, "patches/*.patch", self.recipe_folder, self.export_sources_folder, keep_path=True) + + def configure(self): + self.settings.rm_safe("compiler.libcxx") + self.settings.rm_safe("compiler.cppstd") + + def layout(self): + basic_layout(self, src_folder="src") + + def requirements(self): + self.requires("zlib/[>=1.2.12]") + if self.options.with_openssl: + self.requires("openssl/[~1.1]") + if self.options.with_pam: + self.requires("openpam/20190224") + + def validate(self): + if self.settings.os not in ["Linux", "FreeBSD", "Neutrino"]: + raise ConanInvalidConfiguration(f"{self.ref} is not supported on {self.settings.os}.") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + env = VirtualBuildEnv(self) + env.generate() + + ad = AutotoolsDeps(self) + ad.generate() + + tc = AutotoolsToolchain(self) + tc.configure_args.extend([ + "--with-openssl={}".format("yes" if self.options.with_openssl else "no"), + "--with-pam={}".format("yes" if self.options.with_pam else "no"), + ]) + + if self.options.with_openssl: + openssl = self.dependencies["openssl"] + tc.configure_args.append("--with-ssl-dir={}".format(openssl.package_folder)) + + if self.options.with_sandbox != 'auto': + tc.configure_args.append("--with-sandbox={}".format(self.options.with_sandbox)) + + tc.generate() + + def build(self): + self._patch_sources() + + autotools = Autotools(self) + env = VirtualRunEnv(self) + with env.vars().apply(): + autotools.configure() + + autotools.make() + + def package(self): + autotools = Autotools(self) + + install_target = 'install-nokeys' if cross_building(self) else 'install' + autotools.install(target=install_target) + + copy(self, "LICENCE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"), ignore_case=True) + + def package_info(self): + self.cpp_info.includedirs = [] + self.cpp_info.libdirs = [] + + bindir = os.path.join(self.package_folder, "bin") + self.runenv_info.prepend_path("PATH", bindir) diff --git a/recipes/openssh/all/patches/pselect_timeout.patch b/recipes/openssh/all/patches/pselect_timeout.patch new file mode 100644 index 0000000000000..acea3960aaa11 --- /dev/null +++ b/recipes/openssh/all/patches/pselect_timeout.patch @@ -0,0 +1,23 @@ +--- serverloop.c 2022-10-03 16:51:42.000000000 +0200 ++++ serverloop.c 2023-01-10 16:38:57.721400690 +0100 +@@ -229,13 +229,14 @@ + if (max_time_ms == 0 || client_alive_scheduled) + max_time_ms = 100; + +- if (max_time_ms == 0) +- tsp = NULL; +- else { +- ts.tv_sec = max_time_ms / 1000; +- ts.tv_nsec = 1000000 * (max_time_ms % 1000); +- tsp = &ts; ++ ++ if (max_time_ms == 0) { ++ max_time_ms = 1000; + } ++ ts.tv_sec = max_time_ms / 1000; ++ ts.tv_nsec = 1000000 * (max_time_ms % 1000); ++ tsp = &ts; ++ + + /* Wait for something to happen, or the timeout to expire. */ + ret = ppoll(*pfdp, *npfd_activep, tsp, sigsetp); diff --git a/recipes/openssh/all/test_package/conanfile.py b/recipes/openssh/all/test_package/conanfile.py new file mode 100644 index 0000000000000..ff8bcb63780e9 --- /dev/null +++ b/recipes/openssh/all/test_package/conanfile.py @@ -0,0 +1,32 @@ +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.files import rm +from conan.errors import ConanException +from os.path import exists + + +# It will become the standard on Conan 2.x +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def build(self): + pass + + def test(self): + if not can_run(self): + return + + output_file = "id_rsa" + + if exists(f"{output_file}"): + rm(self, output_file, ".") + + self.run(f"ssh-keygen -t rsa -b 4096 -f {output_file} -N ''", env="conanrun") + + if not exists(f"{output_file}"): + raise ConanException(f"{output_file} does not exist") diff --git a/recipes/openssh/config.yml b/recipes/openssh/config.yml new file mode 100644 index 0000000000000..e495d4050e991 --- /dev/null +++ b/recipes/openssh/config.yml @@ -0,0 +1,5 @@ +versions: + "9.1p1": + folder: all + "8.1p1": + folder: all