diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index 3f96cea2270..4e5de421d8a 100644
--- a/nixos/modules/config/nsswitch.nix
+++ b/nixos/modules/config/nsswitch.nix
@@ -9,6 +9,7 @@ let
inherit (config.services.avahi) nssmdns;
inherit (config.services.samba) nsswins;
ldap = (config.users.ldap.enable && config.users.ldap.nsswitch);
+ sssd = config.services.sssd.enable;
hostArray = [ "files" "mymachines" ]
++ optionals nssmdns [ "mdns_minimal [!UNAVAIL=return]" ]
@@ -18,12 +19,17 @@ let
++ ["myhostname" ];
passwdArray = [ "files" ]
+ ++ optional sssd "sss"
++ optionals ldap [ "ldap" ]
++ [ "mymachines" ];
shadowArray = [ "files" ]
+ ++ optional sssd "sss"
++ optionals ldap [ "ldap" ];
+ servicesArray = [ "files" ]
+ ++ optional sssd "sss";
+
in {
options = {
@@ -60,7 +66,7 @@ in {
networks: files
ethers: files
- services: files
+ services: ${concatStringsSep " " servicesArray}
protocols: files
rpc: files
'';
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index be09fb80e0a..2171809e51b 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -285,6 +285,7 @@
./services/misc/siproxd.nix
./services/misc/sonarr.nix
./services/misc/spice-vdagentd.nix
+ ./services/misc/sssd.nix
./services/misc/subsonic.nix
./services/misc/sundtek.nix
./services/misc/svnserve.nix
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index f9aa4136c8d..96e7c45d496 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -233,6 +233,8 @@ let
account sufficient pam_unix.so
${optionalString use_ldap
"account sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
+ ${optionalString config.services.sssd.enable
+ "account sufficient ${pkgs.sssd}/lib/security/pam_sss.so"}
${optionalString config.krb5.enable
"account sufficient ${pam_krb5}/lib/security/pam_krb5.so"}
@@ -273,6 +275,8 @@ let
"auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"}
${optionalString use_ldap
"auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
+ ${optionalString config.services.sssd.enable
+ "auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass"}
${optionalString config.krb5.enable ''
auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
@@ -288,6 +292,8 @@ let
"password optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString use_ldap
"password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
+ ${optionalString config.services.sssd.enable
+ "password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok"}
${optionalString config.krb5.enable
"password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"}
${optionalString config.services.samba.syncPasswordsByPam
@@ -303,13 +309,15 @@ let
if config.boot.isContainer then "optional" else "required"
} pam_loginuid.so"}
${optionalString cfg.makeHomeDir
- "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022"}
+ "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0022"}
${optionalString cfg.updateWtmp
"session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
${optionalString config.security.pam.enableEcryptfs
"session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
${optionalString use_ldap
"session optional ${pam_ldap}/lib/security/pam_ldap.so"}
+ ${optionalString config.services.sssd.enable
+ "session optional ${pkgs.sssd}/lib/security/pam_sss.so"}
${optionalString config.krb5.enable
"session optional ${pam_krb5}/lib/security/pam_krb5.so"}
${optionalString cfg.otpwAuth
@@ -397,6 +405,16 @@ in
'';
};
+ security.pam.makeHomeDir.skelDirectory = mkOption {
+ type = types.str;
+ default = "/var/empty";
+ example = "/etc/skel";
+ description = ''
+ Path to skeleton directory whose contents are copied to home
+ directories newly created by pam_mkhomedir.
+ '';
+ };
+
security.pam.enableSSHAgentAuth = mkOption {
default = false;
description =
@@ -447,6 +465,7 @@ in
# Include the PAM modules in the system path mostly for the manpages.
[ pkgs.pam ]
++ optional config.users.ldap.enable pam_ldap
+ ++ optional config.services.sssd.enable pkgs.sssd
++ optionals config.krb5.enable [pam_krb5 pam_ccreds]
++ optionals config.security.pam.enableOTPW [ pkgs.otpw ]
++ optionals config.security.pam.oath.enable [ pkgs.oathToolkit ]
diff --git a/nixos/modules/services/misc/nscd-sssd.conf b/nixos/modules/services/misc/nscd-sssd.conf
new file mode 100644
index 00000000000..92380f3e4ba
--- /dev/null
+++ b/nixos/modules/services/misc/nscd-sssd.conf
@@ -0,0 +1,36 @@
+server-user nscd
+threads 1
+paranoia no
+debug-level 0
+
+enable-cache passwd yes
+positive-time-to-live passwd 0
+negative-time-to-live passwd 0
+suggested-size passwd 211
+check-files passwd yes
+persistent passwd no
+shared passwd yes
+
+enable-cache group yes
+positive-time-to-live group 0
+negative-time-to-live group 0
+suggested-size group 211
+check-files group yes
+persistent group no
+shared group yes
+
+enable-cache hosts yes
+positive-time-to-live hosts 600
+negative-time-to-live hosts 5
+suggested-size hosts 211
+check-files hosts yes
+persistent hosts no
+shared hosts yes
+
+enable-cache services yes
+positive-time-to-live services 0
+negative-time-to-live services 0
+suggested-size services 211
+check-files services yes
+persistent services no
+shared services yes
diff --git a/nixos/modules/services/misc/sssd.nix b/nixos/modules/services/misc/sssd.nix
new file mode 100644
index 00000000000..e818f4a4804
--- /dev/null
+++ b/nixos/modules/services/misc/sssd.nix
@@ -0,0 +1,97 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+ cfg = config.services.sssd;
+ nscd = config.services.nscd;
+in {
+ options = {
+ services.sssd = {
+ enable = mkEnableOption "the System Security Services Daemon.";
+
+ config = mkOption {
+ type = types.lines;
+ description = "Contents of sssd.conf.";
+ default = ''
+ [sssd]
+ config_file_version = 2
+ services = nss, pam
+ domains = shadowutils
+
+ [nss]
+
+ [pam]
+
+ [domain/shadowutils]
+ id_provider = proxy
+ proxy_lib_name = files
+ auth_provider = proxy
+ proxy_pam_target = sssd-shadowutils
+ proxy_fast_alias = True
+ '';
+ };
+
+ sshAuthorizedKeysIntegration = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to make sshd look up authorized keys from SSS.
+ For this to work, the ssh SSS service must be enabled in the sssd configuration.
+ '';
+ };
+ };
+ };
+ config = mkMerge [
+ (mkIf cfg.enable {
+ assertions = singleton {
+ assertion = nscd.enable;
+ message = "nscd must be enabled through `services.nscd.enable` for SSSD to work.";
+ };
+
+ systemd.services.sssd = {
+ description = "System Security Services Daemon";
+ wantedBy = [ "multi-user.target" ];
+ before = [ "systemd-user-sessions.service" "nss-user-lookup.target" ];
+ after = [ "network-online.target" "nscd.service" ];
+ requires = [ "network-online.target" "nscd.service" ];
+ wants = [ "nss-user-lookup.target" ];
+ restartTriggers = [
+ config.environment.etc."nscd.conf".source
+ config.environment.etc."sssd/sssd.conf".source
+ ];
+ script = ''
+ export LDB_MODULES_PATH+="''${LDB_MODULES_PATH+:}${pkgs.ldb}/modules/ldb:${pkgs.sssd}/modules/ldb"
+ mkdir -p /var/lib/sss/{pubconf,db,mc,pipes,gpo_cache,secrets} /var/lib/sss/pipes/private /var/lib/sss/pubconf/krb5.include.d
+ ${pkgs.sssd}/bin/sssd -D
+ '';
+ serviceConfig = {
+ Type = "forking";
+ PIDFile = "/run/sssd.pid";
+ };
+ };
+
+ environment.etc."sssd/sssd.conf" = {
+ text = cfg.config;
+ mode = "0400";
+ };
+
+ system.nssModules = optional cfg.enable pkgs.sssd;
+ services.nscd.config = builtins.readFile ./nscd-sssd.conf;
+ services.dbus.packages = [ pkgs.sssd ];
+ })
+
+ (mkIf cfg.sshAuthorizedKeysIntegration {
+ # Ugly: sshd refuses to start if a store path is given because /nix/store is group-writable.
+ # So indirect by a symlink.
+ environment.etc."ssh/authorized_keys_command" = {
+ mode = "0755";
+ text = ''
+ #!/bin/sh
+ exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
+ '';
+ };
+ services.openssh.extraConfig = ''
+ AuthorizedKeysCommand /etc/ssh/authorized_keys_command
+ AuthorizedKeysCommandUser nobody
+ '';
+ })];
+}
diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix
index d98ef8a306d..eb4b5281c7c 100644
--- a/nixos/modules/services/system/nscd.nix
+++ b/nixos/modules/services/system/nscd.nix
@@ -9,8 +9,6 @@ let
inherit (lib) singleton;
- cfgFile = pkgs.writeText "nscd.conf" cfg.config;
-
in
{
@@ -41,6 +39,7 @@ in
###### implementation
config = mkIf cfg.enable {
+ environment.etc."nscd.conf".text = cfg.config;
users.extraUsers.nscd =
{ isSystemUser = true;
@@ -61,10 +60,14 @@ in
mkdir -m 0755 -p /var/db/nscd
'';
- restartTriggers = [ config.environment.etc.hosts.source config.environment.etc."nsswitch.conf".source ];
+ restartTriggers = [
+ config.environment.etc.hosts.source
+ config.environment.etc."nsswitch.conf".source
+ config.environment.etc."nscd.conf".source
+ ];
serviceConfig =
- { ExecStart = "@${pkgs.glibc.bin}/sbin/nscd nscd -f ${cfgFile}";
+ { ExecStart = "@${pkgs.glibc.bin}/sbin/nscd nscd";
Type = "forking";
PIDFile = "/run/nscd/nscd.pid";
Restart = "always";
@@ -79,7 +82,7 @@ in
# its pid. So wait until it's ready.
postStart =
''
- while ! ${pkgs.glibc.bin}/sbin/nscd -g -f ${cfgFile} > /dev/null; do
+ while ! ${pkgs.glibc.bin}/sbin/nscd -g > /dev/null; do
sleep 0.2
done
'';
diff --git a/pkgs/os-specific/linux/autofs/default.nix b/pkgs/os-specific/linux/autofs/default.nix
index 4401eb24cb4..d2d2c4a3988 100644
--- a/pkgs/os-specific/linux/autofs/default.nix
+++ b/pkgs/os-specific/linux/autofs/default.nix
@@ -1,5 +1,5 @@
{ stdenv, lib, fetchurl, flex, bison, linuxHeaders, libtirpc, utillinux, nfs-utils, e2fsprogs
-, libxml2 }:
+, libxml2, kerberos, kmod, openldap, sssd, cyrus_sasl, openssl }:
let
version = "5.1.2";
@@ -13,7 +13,9 @@ in stdenv.mkDerivation {
};
preConfigure = ''
- configureFlags="--enable-force-shutdown --enable-ignore-busy --with-path=$PATH"
+ configureFlags="--enable-force-shutdown --enable-ignore-busy --with-path=$PATH --with-openldap=${openldap} --with-sasl=${cyrus_sasl}"
+ export sssldir="${sssd}/lib/sssd/modules"
+ export HAVE_SSS_AUTOFS=1
export MOUNT=${lib.getBin utillinux}/bin/mount
export MOUNT_NFS=${lib.getBin nfs-utils}/bin/mount.nfs
@@ -29,7 +31,8 @@ in stdenv.mkDerivation {
#make install SUBDIRS="samples" # impure!
'';
- buildInputs = [ linuxHeaders libtirpc libxml2 ];
+ buildInputs = [ linuxHeaders libtirpc libxml2 kerberos kmod openldap sssd
+ openssl cyrus_sasl ];
nativeBuildInputs = [ flex bison ];
diff --git a/pkgs/os-specific/linux/sssd/default.nix b/pkgs/os-specific/linux/sssd/default.nix
new file mode 100644
index 00000000000..d50848af3dc
--- /dev/null
+++ b/pkgs/os-specific/linux/sssd/default.nix
@@ -0,0 +1,87 @@
+{ stdenv, fetchurl, pkgs, lib, glibc, augeas, bind, c-ares,
+ cyrus_sasl, ding-libs, libnl, libunistring, nss, samba, libnfsidmap, doxygen,
+ python, python3, pam, popt, talloc, tdb, tevent, pkgconfig, ldb, openldap,
+ pcre, kerberos, cifs_utils, glib, keyutils, dbus, fakeroot, libxslt, libxml2,
+ docbook_xml_xslt, ldap, systemd, nspr, check, cmocka, uid_wrapper,
+ nss_wrapper, docbook_xml_dtd_44, ncurses, Po4a, http-parser, jansson }:
+
+let
+ name = "sssd-${version}";
+ version = "1.14.2";
+
+ docbookFiles = "${pkgs.docbook_xml_xslt}/share/xml/docbook-xsl/catalog.xml:${pkgs.docbook_xml_dtd_44}/xml/dtd/docbook/catalog.xml";
+in
+stdenv.mkDerivation {
+ inherit name;
+ inherit version;
+
+ src = fetchurl {
+ url = "https://fedorahosted.org/released/sssd/${name}.tar.gz";
+ sha1 = "167b2216c536035175ff041d0449e0a874c68601";
+ };
+
+ preConfigure = ''
+ export SGML_CATALOG_FILES="${docbookFiles}"
+ export PYTHONPATH=${ldap}/lib/python2.7/site-packages
+ export PATH=$PATH:${pkgs.openldap}/libexec
+ export CPATH=${pkgs.libxml2.dev}/include/libxml2
+
+ configureFlagsArray=(
+ --prefix=$out
+ --sysconfdir=/etc
+ --localstatedir=/var
+ --enable-pammoddir=$out/lib/security
+ --with-os=fedora
+ --with-pid-path=/run
+ --with-python2-bindings
+ --with-python3-bindings
+ --with-syslog=journald
+ --without-selinux
+ --without-semanage
+ --with-xml-catalog-path=''${SGML_CATALOG_FILES%%:*}
+ --with-ldb-lib-dir=$out/modules/ldb
+ --with-nscd=${glibc.bin}/sbin/nscd
+ )
+ '';
+
+ enableParallelBuilding = true;
+ buildInputs = [ augeas bind c-ares cyrus_sasl ding-libs libnl libunistring nss
+ samba libnfsidmap doxygen python python3 popt
+ talloc tdb tevent pkgconfig ldb pam openldap pcre kerberos
+ cifs_utils glib keyutils dbus fakeroot libxslt libxml2
+ ldap systemd nspr check cmocka uid_wrapper
+ nss_wrapper ncurses Po4a http-parser jansson ];
+
+ makeFlags = [
+ "SGML_CATALOG_FILES=${docbookFiles}"
+ ];
+
+ installFlags = [
+ "sysconfdir=$(out)/etc"
+ "localstatedir=$(out)/var"
+ "pidpath=$(out)/run"
+ "sss_statedir=$(out)/var/lib/sss"
+ "logpath=$(out)/var/log/sssd"
+ "pubconfpath=$(out)/var/lib/sss/pubconf"
+ "dbpath=$(out)/var/lib/sss/db"
+ "mcpath=$(out)/var/lib/sss/mc"
+ "pipepath=$(out)/var/lib/sss/pipes"
+ "gpocachepath=$(out)/var/lib/sss/gpo_cache"
+ "secdbpath=$(out)/var/lib/sss/secrets"
+ "initdir=$(out)/rc.d/init"
+ ];
+
+ postInstall = ''
+ rm -rf "$out"/run
+ rm -rf "$out"/rc.d
+ rm -f "$out"/modules/ldb/memberof.la
+ find "$out" -depth -type d -exec rmdir --ignore-fail-on-non-empty {} \;
+ '';
+
+ meta = with stdenv.lib; {
+ description = "System Security Services Daemon";
+ homepage = https://fedorahosted.org/sssd/;
+ license = licenses.gpl3;
+ maintainers = [ maintainers.e-user ];
+ };
+}
diff --git a/pkgs/tools/misc/ding-libs/default.nix b/pkgs/tools/misc/ding-libs/default.nix
new file mode 100644
index 00000000000..547e3fb49eb
--- /dev/null
+++ b/pkgs/tools/misc/ding-libs/default.nix
@@ -0,0 +1,27 @@
+{ stdenv, fetchurl, glibc, doxygen, check }:
+
+let
+ name = "ding-libs";
+ version = "0.6.0";
+in stdenv.mkDerivation {
+ inherit name;
+ inherit version;
+
+ src = fetchurl {
+ url = "https://fedorahosted.org/released/${name}/${name}-${version}.tar.gz";
+ sha1 = "c8ec86cb93a26e013a13b12a7b0b3fbc1bca16c1";
+ };
+
+ enableParallelBuilding = true;
+ buildInputs = [ glibc doxygen check ];
+
+ buildFlags = "docs";
+ doCheck = true;
+
+ meta = {
+ description = "'D is not GLib' utility libraries";
+ homepage = https://fedorahosted.org/sssd/;
+ maintainers = with stdenv.lib.maintainers; [ e-user ];
+ license = [ stdenv.lib.licenses.gpl3 stdenv.lib.licenses.lgpl3 ];
+ };
+}
diff --git a/pkgs/tools/text/sgml/jade/default.nix b/pkgs/tools/text/sgml/jade/default.nix
new file mode 100644
index 00000000000..ffbf9784f80
--- /dev/null
+++ b/pkgs/tools/text/sgml/jade/default.nix
@@ -0,0 +1,38 @@
+{ stdenv, fetchurl, pkgs, gcc, gzip, gnum4 }:
+
+stdenv.mkDerivation (rec {
+ name = "jade";
+ version = "1.2.1";
+ debpatch = "47.3";
+
+ src = fetchurl {
+ url = "ftp://ftp.jclark.com/pub/${name}/${name}-${version}.tar.gz";
+ sha256 = "84e2f8a2a87aab44f86a46b71405d4f919b219e4c73e03a83ab6c746a674b187";
+ };
+
+ patchsrc = fetchurl {
+ url = "http://ftp.debian.org/debian/pool/main/j/jade/jade_${version}-${debpatch}.diff.gz";
+ sha256 = "8e94486898e3503308805f856a65ba5b499a6f21994151270aa743de48305464";
+ };
+
+ patches = [ patchsrc ];
+
+ buildInputs = [ gcc gzip gnum4 ];
+
+ NIX_CFLAGS_COMPILE = [ "-Wno-deprecated" ];
+
+ preInstall = ''
+ install -d -m755 "$out"/lib
+ '';
+
+ postInstall = ''
+ mv "$out/bin/sx" "$out/bin/sgml2xml"
+ '';
+
+ meta = {
+ description = "James Clark's DSSSL Engine";
+ license = "custom";
+ homepage = http://www.jclark.com/jade/;
+ maintainers = with stdenv.lib.maintainers; [ e-user ];
+ };
+})
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index cfb2551e5a8..2bdabdff4dd 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -2320,6 +2320,8 @@ in
jaaa = callPackage ../applications/audio/jaaa { };
+ jade = callPackage ../tools/text/sgml/jade { };
+
jd-gui = callPackage_i686 ../tools/security/jd-gui { };
jdiskreport = callPackage ../tools/misc/jdiskreport { };
@@ -4171,6 +4173,13 @@ in
openssl = null;
};
+ ding-libs = callPackage ../tools/misc/ding-libs { };
+
+ sssd = callPackage ../os-specific/linux/sssd {
+ inherit (perlPackages) Po4a;
+ inherit (python27Packages) ldap;
+ };
+
vtun = callPackage ../tools/networking/vtun { };
wakatime = callPackage ../tools/misc/wakatime { };
diff --git a/pkgs/top-level/perl-packages.nix b/pkgs/top-level/perl-packages.nix
index 5bc0e81106b..b8c5e637870 100644
--- a/pkgs/top-level/perl-packages.nix
+++ b/pkgs/top-level/perl-packages.nix
@@ -10394,6 +10394,34 @@ let self = _self // overrides; _self = with self; {
};
};
+ Po4a = buildPerlPackage rec {
+ name = "po4a-0.47";
+ src = fetchurl {
+ url = "https://alioth.debian.org/frs/download.php/file/4142/po4a-0.47.tar.gz";
+ sha256 = "5010e1b7df1115cbd475f46587fc05fefc97301f9bba0c2f15106005ca017507";
+ };
+ propagatedBuildInputs = [ pkgs.docbook_xml_xslt TextWrapI18N LocaleGettext TermReadKey SGMLSpm ModuleBuild UnicodeLineBreak ModuleBuild ];
+ buildInputs = [ pkgs.gettext pkgs.libxslt pkgs.glibcLocales pkgs.docbook_xml_dtd_412 pkgs.docbook_sgml_dtd_41 pkgs.texlive.combined.scheme-basic pkgs.jade ];
+ LC_ALL="en_US.UTF-8";
+ SGML_CATALOG_FILES = "${pkgs.docbook_xml_dtd_412}/xml/dtd/docbook/catalog.xml";
+ preConfigure = ''
+ touch Makefile.PL
+ export PERL_MB_OPT="--install_base=$out --prefix=$out"
+ substituteInPlace Po4aBuilder.pm --replace "\$self->install_sets(\$self->installdirs)->{'bindoc'}" "'$out/share/man/man1'"
+ '';
+ buildPhase = "perl Build.PL --install_base=$out; ./Build build";
+ installPhase = "./Build install";
+ checkPhase = ''
+ export SGML_CATALOG_FILES=${pkgs.docbook_sgml_dtd_41}/sgml/dtd/docbook-4.1/docbook.cat
+ ./Build test
+ '';
+ meta = {
+ homepage = https://po4a.alioth.debian.org/;
+ description = "tools for helping translation of documentation";
+ license = with stdenv.lib.licenses; [ gpl2 ];
+ };
+ };
+
PPI = buildPerlPackage {
name = "PPI-1.220";
src = fetchurl {
@@ -13722,6 +13750,22 @@ let self = _self // overrides; _self = with self; {
};
};
+ TextWrapI18N = buildPerlPackage {
+ name = "Text-WrapI18N-0.06";
+ src = fetchurl {
+ url = http://search.cpan.org/CPAN/authors/id/K/KU/KUBOTA/Text-WrapI18N-0.06.tar.gz;
+ sha256 = "4bd29a17f0c2c792d12c1005b3c276f2ab0fae39c00859ae1741d7941846a488";
+ };
+ propagatedBuildInputs = [ pkgs.glibc TextCharWidth ];
+ preConfigure = ''
+ substituteInPlace WrapI18N.pm --replace '/usr/bin/locale' '${pkgs.glibc}/bin/locale'
+ '';
+ meta = {
+ description = "Line wrapping module with support for multibyte, fullwidth, and combining characters and languages without whitespaces between words";
+ license = with stdenv.lib.licenses; [ artistic1 gpl2 ];
+ };
+ };
+
TextWrapper = buildPerlPackage {
name = "Text-Wrapper-1.05";
src = fetchurl {