1{
2 pname,
3 version,
4 extraDesc ? "",
5 src,
6 extraPatches ? [ ],
7 extraNativeBuildInputs ? [ ],
8 extraConfigureFlags ? [ ],
9 extraMeta ? { },
10}:
11
12{
13 lib,
14 stdenv,
15 # This *is* correct, though unusual. as a way of getting krb5-config from the
16 # package without splicing See: https://github.com/NixOS/nixpkgs/pull/107606
17 pkgs,
18 fetchurl,
19 fetchpatch,
20 autoreconfHook,
21 zlib,
22 openssl,
23 softhsm,
24 libedit,
25 ldns,
26 pkg-config,
27 pam,
28 libredirect,
29 etcDir ? null,
30 withKerberos ? false,
31 withLdns ? true,
32 krb5,
33 libfido2,
34 libxcrypt,
35 hostname,
36 nixosTests,
37 withSecurityKey ? !stdenv.hostPlatform.isStatic,
38 withFIDO ? stdenv.hostPlatform.isUnix && !stdenv.hostPlatform.isMusl && withSecurityKey,
39 withPAM ? stdenv.hostPlatform.isLinux,
40 # Attempts to mlock the entire sshd process on startup to prevent swapping.
41 # Currently disabled when PAM support is enabled due to crashes
42 # See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1103418
43 withLinuxMemlock ? (stdenv.hostPlatform.isLinux && !withPAM),
44 linkOpenssl ? true,
45 isNixos ? stdenv.hostPlatform.isLinux,
46}:
47
48# FIDO support requires SK support
49assert withFIDO -> withSecurityKey;
50
51stdenv.mkDerivation (finalAttrs: {
52 inherit pname version src;
53
54 patches = [
55 # Making openssh pass the LOCALE_ARCHIVE variable to the forked session processes,
56 # so the session 'bash' will receive the proper locale archive, and thus process
57 # UTF-8 properly.
58 ./locale_archive.patch
59
60 # See discussion in https://github.com/NixOS/nixpkgs/pull/16966
61 ./dont_create_privsep_path.patch
62 ]
63 ++ extraPatches;
64
65 postPatch =
66 # On Hydra this makes installation fail (sometimes?),
67 # and nix store doesn't allow such fancy permission bits anyway.
68 ''
69 substituteInPlace Makefile.in --replace '$(INSTALL) -m 4711' '$(INSTALL) -m 0711'
70 '';
71
72 strictDeps = true;
73 nativeBuildInputs = [
74 autoreconfHook
75 pkg-config
76 ]
77 # This is not the same as the krb5 from the inputs! pkgs.krb5 is
78 # needed here to access krb5-config in order to cross compile. See:
79 # https://github.com/NixOS/nixpkgs/pull/107606
80 ++ lib.optional withKerberos pkgs.krb5
81 ++ extraNativeBuildInputs;
82 buildInputs = [
83 zlib
84 libedit
85 ]
86 ++ [ (if linkOpenssl then openssl else libxcrypt) ]
87 ++ lib.optional withFIDO libfido2
88 ++ lib.optional withKerberos krb5
89 ++ lib.optional withLdns ldns
90 ++ lib.optional withPAM pam;
91
92 preConfigure = ''
93 # Setting LD causes `configure' and `make' to disagree about which linker
94 # to use: `configure' wants `gcc', but `make' wants `ld'.
95 unset LD
96 '';
97
98 env = lib.optionalAttrs isNixos {
99 # openssh calls passwd to allow the user to reset an expired password, but nixos
100 # doesn't ship it at /usr/bin/passwd.
101 PATH_PASSWD_PROG = "/run/wrappers/bin/passwd";
102 };
103
104 # I set --disable-strip because later we strip anyway. And it fails to strip
105 # properly when cross building.
106 configureFlags = [
107 "--sbindir=\${out}/bin"
108 "--localstatedir=/var"
109 "--with-pid-dir=/run"
110 "--with-mantype=doc"
111 "--with-libedit=yes"
112 "--disable-strip"
113 (lib.withFeature withPAM "pam")
114 ]
115 ++ lib.optional (etcDir != null) "--sysconfdir=${etcDir}"
116 ++ lib.optional (!withSecurityKey) "--disable-security-key"
117 ++ lib.optional withFIDO "--with-security-key-builtin=yes"
118 ++ lib.optional withKerberos (
119 assert krb5 != null;
120 "--with-kerberos5=${lib.getDev krb5}"
121 )
122 ++ lib.optional stdenv.hostPlatform.isDarwin "--disable-libutil"
123 ++ lib.optional (!linkOpenssl) "--without-openssl"
124 ++ lib.optional withLdns "--with-ldns"
125 ++ lib.optional stdenv.hostPlatform.isOpenBSD "--with-bsd-auth"
126 ++ lib.optional withLinuxMemlock "--with-linux-memlock-onfault"
127 ++ extraConfigureFlags;
128
129 ${if stdenv.hostPlatform.isStatic then "NIX_LDFLAGS" else null} = [
130 "-laudit"
131 ]
132 ++ lib.optional withKerberos "-lkeyutils"
133 ++ lib.optional withLdns "-lcrypto";
134
135 buildFlags = [ "SSH_KEYSIGN=ssh-keysign" ];
136
137 enableParallelBuilding = true;
138
139 hardeningEnable = [ "pie" ];
140
141 doCheck = false;
142 enableParallelChecking = false;
143 nativeCheckInputs = [
144 openssl
145 ]
146 ++ lib.optional (!stdenv.hostPlatform.isDarwin) hostname
147 ++ lib.optional (!stdenv.hostPlatform.isDarwin && !stdenv.hostPlatform.isMusl) softhsm;
148
149 preCheck =
150 lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
151 # construct a dummy HOME
152 export HOME=$(realpath ../dummy-home)
153 mkdir -p ~/.ssh
154
155 # construct a dummy /etc/passwd file for the sshd under test
156 # to use to look up the connecting user
157 DUMMY_PASSWD=$(realpath ../dummy-passwd)
158 cat > $DUMMY_PASSWD <<EOF
159 $(whoami)::$(id -u):$(id -g)::$HOME:$SHELL
160 EOF
161
162 # we need to NIX_REDIRECTS /etc/passwd both for processes
163 # invoked directly and those invoked by the "remote" session
164 cat > ~/.ssh/environment.base <<EOF
165 NIX_REDIRECTS=/etc/passwd=$DUMMY_PASSWD
166 ${lib.optionalString (
167 !stdenv.buildPlatform.isStatic
168 ) "LD_PRELOAD=${libredirect}/lib/libredirect.so"}
169 EOF
170
171 # use an ssh environment file to ensure environment is set
172 # up appropriately for build environment even when no shell
173 # is invoked by the ssh session. otherwise the PATH will
174 # only contain default unix paths like /bin which we don't
175 # have in our build environment
176 cat - regress/test-exec.sh > regress/test-exec.sh.new <<EOF
177 cp $HOME/.ssh/environment.base $HOME/.ssh/environment
178 echo "PATH=\$PATH" >> $HOME/.ssh/environment
179 EOF
180 mv regress/test-exec.sh.new regress/test-exec.sh
181
182 # explicitly enable the PermitUserEnvironment feature
183 substituteInPlace regress/test-exec.sh \
184 --replace \
185 'cat << EOF > $OBJ/sshd_config' \
186 $'cat << EOF > $OBJ/sshd_config\n\tPermitUserEnvironment yes'
187
188 # some tests want to use files under /bin as example files
189 for f in regress/sftp-cmds.sh regress/forwarding.sh; do
190 substituteInPlace $f --replace '/bin' "$(dirname $(type -p ls))"
191 done
192
193 # set up NIX_REDIRECTS for direct invocations
194 set -a; source ~/.ssh/environment.base; set +a
195 ''
196 + lib.optionalString (!stdenv.hostPlatform.isDarwin && !stdenv.hostPlatform.isMusl) ''
197 # The extra tests check PKCS#11 interactions, which softhsm emulates with software only
198 substituteInPlace regress/test-exec.sh \
199 --replace /usr/local/lib/softhsm/libsofthsm2.so ${lib.getLib softhsm}/lib/softhsm/libsofthsm2.so
200 '';
201 # integration tests hard to get working on darwin with its shaky
202 # sandbox
203 # t-exec tests fail on musl
204 checkTarget =
205 lib.optionals (!stdenv.hostPlatform.isDarwin && !stdenv.hostPlatform.isMusl) [
206 "t-exec"
207 "extra-tests"
208 ]
209 # other tests are less demanding of the environment
210 ++ [
211 "unit"
212 "file-tests"
213 "interop-tests"
214 ];
215
216 postInstall = ''
217 # Install ssh-copy-id, it's very useful.
218 cp contrib/ssh-copy-id $out/bin/
219 chmod +x $out/bin/ssh-copy-id
220 cp contrib/ssh-copy-id.1 $out/share/man/man1/
221 '';
222
223 installTargets = [ "install-nokeys" ];
224 installFlags = [
225 "sysconfdir=\${out}/etc/ssh"
226 ];
227
228 doInstallCheck = true;
229 installCheckPhase = ''
230 for binary in ssh sshd; do
231 $out/bin/$binary -V 2>&1 | grep -P "$(printf '^OpenSSH_\\Q%s\\E,' "$version")"
232 done
233 '';
234
235 passthru = {
236 inherit withKerberos;
237 tests = {
238 borgbackup-integration = nixosTests.borgbackup;
239 nixosTest = nixosTests.openssh;
240 initrd-network-openssh = nixosTests.initrd-network-ssh;
241 openssh = finalAttrs.finalPackage.overrideAttrs (previousAttrs: {
242 pname = previousAttrs.pname + "-test";
243 doCheck = true;
244 });
245 };
246 };
247
248 meta = {
249 description = "Implementation of the SSH protocol${extraDesc}";
250 homepage = "https://www.openssh.com/";
251 changelog = "https://www.openssh.com/releasenotes.html";
252 license = lib.licenses.bsd2;
253 platforms = lib.platforms.unix ++ lib.platforms.windows;
254 maintainers = extraMeta.maintainers or [ ];
255 mainProgram = "ssh";
256 }
257 // extraMeta;
258})