summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/config/gnu.nix9
-rw-r--r--nixos/modules/services/networking/ssh/lshd.nix176
-rw-r--r--pkgs/tools/networking/lsh/default.nix49
-rw-r--r--pkgs/tools/networking/lsh/lshd-no-root-login.patch16
-rw-r--r--pkgs/tools/networking/lsh/pam-service-name.patch14
-rw-r--r--pkgs/top-level/all-packages.nix4
6 files changed, 267 insertions, 1 deletions
diff --git a/nixos/modules/config/gnu.nix b/nixos/modules/config/gnu.nix
index 5cc41ce8690..f8c35b440d1 100644
--- a/nixos/modules/config/gnu.nix
+++ b/nixos/modules/config/gnu.nix
@@ -9,7 +9,8 @@ with lib;
       default = false;
       description =
         '' When enabled, GNU software is chosen by default whenever a there is
-           a choice between GNU and non-GNU software.
+           a choice between GNU and non-GNU software (e.g., GNU lsh
+           vs. OpenSSH).
         '';
     };
   };
@@ -32,6 +33,12 @@ with lib;
     boot.loader.grub.enable = !pkgs.stdenv.isArm;
     boot.loader.grub.version = 2;
 
+    # GNU lsh.
+    services.openssh.enable = false;
+    services.lshd.enable = true;
+    programs.ssh.startAgent = false;
+    services.xserver.startGnuPGAgent = true;
+
     # TODO: GNU dico.
     # TODO: GNU Inetutils' inetd.
     # TODO: GNU Pies.
diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix
new file mode 100644
index 00000000000..661a6a52463
--- /dev/null
+++ b/nixos/modules/services/networking/ssh/lshd.nix
@@ -0,0 +1,176 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  inherit (pkgs) lsh;
+
+  cfg = config.services.lshd;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.lshd = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to enable the GNU lshd SSH2 daemon, which allows
+          secure remote login.
+        '';
+      };
+
+      portNumber = mkOption {
+        default = 22;
+        description = ''
+          The port on which to listen for connections.
+        '';
+      };
+
+      interfaces = mkOption {
+        default = [];
+        description = ''
+          List of network interfaces where listening for connections.
+          When providing the empty list, `[]', lshd listens on all
+          network interfaces.
+        '';
+        example = [ "localhost" "1.2.3.4:443" ];
+      };
+
+      hostKey = mkOption {
+        default = "/etc/lsh/host-key";
+        description = ''
+          Path to the server's private key.  Note that this key must
+          have been created, e.g., using "lsh-keygen --server |
+          lsh-writekey --server", so that you can run lshd.
+        '';
+      };
+
+      syslog = mkOption {
+        default = true;
+        description = ''Whether to enable syslog output.'';
+      };
+
+      passwordAuthentication = mkOption {
+        default = true;
+        description = ''Whether to enable password authentication.'';
+      };
+
+      publicKeyAuthentication = mkOption {
+        default = true;
+        description = ''Whether to enable public key authentication.'';
+      };
+
+      rootLogin = mkOption {
+        default = false;
+        description = ''Whether to enable remote root login.'';
+      };
+
+      loginShell = mkOption {
+        default = null;
+        description = ''
+          If non-null, override the default login shell with the
+          specified value.
+        '';
+        example = "/nix/store/xyz-bash-10.0/bin/bash10";
+      };
+
+      srpKeyExchange = mkOption {
+        default = false;
+        description = ''
+          Whether to enable SRP key exchange and user authentication.
+        '';
+      };
+
+      tcpForwarding = mkOption {
+        default = true;
+        description = ''Whether to enable TCP/IP forwarding.'';
+      };
+
+      x11Forwarding = mkOption {
+        default = true;
+        description = ''Whether to enable X11 forwarding.'';
+      };
+
+      subsystems = mkOption {
+        description = ''
+          List of subsystem-path pairs, where the head of the pair
+          denotes the subsystem name, and the tail denotes the path to
+          an executable implementing it.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    services.lshd.subsystems = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ];
+
+    systemd.services.lshd = {
+      description = "GNU lshd SSH2 daemon";
+
+      after = [ "network-interfaces.target" ];
+
+      wantedBy = [ "multi-user.target" ];
+
+      environment = {
+        LD_LIBRARY_PATH = config.system.nssModules.path;
+      };
+
+      preStart = ''
+        test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
+        test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
+
+        if ! test -f /var/spool/lsh/yarrow-seed-file
+        then
+            # XXX: It would be nice to provide feedback to the
+            # user when this fails, so that they can retry it
+            # manually.
+            ${lsh}/bin/lsh-make-seed --sloppy \
+               -o /var/spool/lsh/yarrow-seed-file
+        fi
+
+        if ! test -f "${cfg.hostKey}"
+        then
+            ${lsh}/bin/lsh-keygen --server | \
+            ${lsh}/bin/lsh-writekey --server -o "${cfg.hostKey}"
+        fi
+      '';
+
+      script = with cfg; ''
+        ${lsh}/sbin/lshd --daemonic \
+          --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
+          -p ${toString portNumber} \
+          ${if interfaces == [] then ""
+            else (concatStrings (map (i: "--interface=\"${i}\"")
+                                     interfaces))} \
+          -h "${hostKey}" \
+          ${if !syslog then "--no-syslog" else ""} \
+          ${if passwordAuthentication then "--password" else "--no-password" } \
+          ${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
+          ${if rootLogin then "--root-login" else "--no-root-login" } \
+          ${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
+          ${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
+          ${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
+          ${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
+          --subsystems=${concatStringsSep ","
+                                          (map (pair: (head pair) + "=" +
+                                                      (head (tail pair)))
+                                               subsystems)}
+      '';
+    };
+
+    security.pam.services.lshd = {};
+  };
+}
diff --git a/pkgs/tools/networking/lsh/default.nix b/pkgs/tools/networking/lsh/default.nix
new file mode 100644
index 00000000000..77d268f3a47
--- /dev/null
+++ b/pkgs/tools/networking/lsh/default.nix
@@ -0,0 +1,49 @@
+{ stdenv, fetchurl, gperf, guile, gmp, zlib, liboop, readline, gnum4, pam
+, nettools, lsof, procps }:
+
+stdenv.mkDerivation rec {
+  name = "lsh-2.0.4";
+  src = fetchurl {
+    url = "mirror://gnu/lsh/${name}.tar.gz";
+    sha256 = "614b9d63e13ad3e162c82b6405d1f67713fc622a8bc11337e72949d613713091";
+  };
+
+  patches = [ ./pam-service-name.patch ./lshd-no-root-login.patch ];
+
+  preConfigure = ''
+    # Patch `lsh-make-seed' so that it can gather enough entropy.
+    sed -i "src/lsh-make-seed.c" \
+        -e "s|/usr/sbin/arp|${nettools}/sbin/arp|g ;
+            s|/usr/bin/netstat|${nettools}/bin/netstat|g ;
+            s|/usr/local/bin/lsof|${lsof}/bin/lsof|g ;
+            s|/bin/vmstat|${procps}/bin/vmstat|g ;
+            s|/bin/ps|${procps}/bin/sp|g ;
+            s|/usr/bin/w|${procps}/bin/w|g ;
+            s|/usr/bin/df|$(type -P df)|g ;
+            s|/usr/bin/ipcs|$(type -P ipcs)|g ;
+            s|/usr/bin/uptime|$(type -P uptime)|g"
+
+    # Skip the `configure' script that checks whether /dev/ptmx & co. work as
+    # expected, because it relies on impurities (for instance, /dev/pts may
+    # be unavailable in chroots.)
+    export lsh_cv_sys_unix98_ptys=yes
+  '';
+
+  buildInputs = [ gperf guile gmp zlib liboop readline gnum4 pam ];
+
+  meta = {
+    description = "GPL'd implementation of the SSH protocol";
+
+    longDescription = ''
+      lsh is a free implementation (in the GNU sense) of the ssh
+      version 2 protocol, currently being standardised by the IETF
+      SECSH working group.
+    '';
+
+    homepage = http://www.lysator.liu.se/~nisse/lsh/;
+    license = stdenv.lib.licenses.gpl2Plus;
+
+    maintainers = [ ];
+    platforms = [ "x86_64-linux" ];
+  };
+}
diff --git a/pkgs/tools/networking/lsh/lshd-no-root-login.patch b/pkgs/tools/networking/lsh/lshd-no-root-login.patch
new file mode 100644
index 00000000000..9dd81de3fbc
--- /dev/null
+++ b/pkgs/tools/networking/lsh/lshd-no-root-login.patch
@@ -0,0 +1,16 @@
+Correctly handle the `--no-root-login' option.
+
+--- lsh-2.0.4/src/lshd.c	2006-05-01 13:47:44.000000000 +0200
++++ lsh-2.0.4/src/lshd.c	2009-09-08 12:20:36.000000000 +0200
+@@ -758,6 +758,10 @@ main_argp_parser(int key, char *arg, str
+       self->allow_root = 1;
+       break;
+ 
++    case OPT_NO_ROOT_LOGIN:
++      self->allow_root = 0;
++      break;
++
+     case OPT_KERBEROS_PASSWD:
+       self->pw_helper = PATH_KERBEROS_HELPER;
+       break;
+
diff --git a/pkgs/tools/networking/lsh/pam-service-name.patch b/pkgs/tools/networking/lsh/pam-service-name.patch
new file mode 100644
index 00000000000..6a6156855c5
--- /dev/null
+++ b/pkgs/tools/networking/lsh/pam-service-name.patch
@@ -0,0 +1,14 @@
+Tell `lsh-pam-checkpw', the PAM password helper program, to use a more
+descriptive service name.
+
+--- lsh-2.0.4/src/lsh-pam-checkpw.c	2003-02-16 22:30:10.000000000 +0100
++++ lsh-2.0.4/src/lsh-pam-checkpw.c	2008-11-28 16:16:58.000000000 +0100
+@@ -38,7 +38,7 @@
+ #include <security/pam_appl.h>
+ 
+ #define PWD_MAXLEN 1024
+-#define SERVICE_NAME "other"
++#define SERVICE_NAME "lshd"
+ #define TIMEOUT 600 
+ 
+ static int
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index a4dbe1aca1b..81df0d777a6 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -2452,6 +2452,10 @@ in
 
   lsb-release = callPackage ../os-specific/linux/lsb-release { };
 
+  # lsh installs `bin/nettle-lfib-stream' and so does Nettle.  Give the
+  # former a lower priority than Nettle.
+  lsh = lowPrio (callPackage ../tools/networking/lsh { });
+
   lshw = callPackage ../tools/system/lshw { };
 
   lxc = callPackage ../os-specific/linux/lxc { };