From 62f28d30a069135f9c48678507203958adfc334f Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Thu, 29 Sep 2016 13:51:44 +0300 Subject: Moved everything into ./modules --- modules/apps/cli.nix | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 modules/apps/cli.nix (limited to 'modules/apps/cli.nix') diff --git a/modules/apps/cli.nix b/modules/apps/cli.nix new file mode 100644 index 0000000..00365d8 --- /dev/null +++ b/modules/apps/cli.nix @@ -0,0 +1,140 @@ +{ config, pkgs, lib, ...}: + +let + + inherit (builtins) + toString ; + inherit (lib) + concatMapStrings filterAttrs mapAttrsToList mkOption + types unique ; + inherit (types) + attrsOf path str submodule ; + + explicit = filterAttrs (n: v: n != "_module" && v != null); + apps = explicit config.nixsap.apps.cli; + + exec = name: { user, command, ... }: + let + uid = toString config.users.users.${user}.uid; + gid = uid; + src = pkgs.writeText "${name}.c" '' + #include + #include + #include + #include + #include + #include + + int main (int __attribute__((unused)) argc, char *argv[]) + { + int rc; + + if (getuid() != ${uid}) { + if (geteuid() != 0) { + fprintf(stderr, "Forbidden.\n"); + return EXIT_FAILURE; + } + + rc = initgroups("${user}", ${gid}); + if (0 != rc) { + perror("initgroups()"); + return EXIT_FAILURE; + } + + rc = setgid(${gid}); + if (0 != rc) { + perror("setgid()"); + return EXIT_FAILURE; + } + + rc = setuid(${uid}); + if (0 != rc) { + perror("setuid()"); + return EXIT_FAILURE; + } + + if ((getuid() != ${uid}) || (geteuid() != ${uid})) { + fprintf(stderr, "Something went wrong.\n"); + return EXIT_FAILURE; + } + + struct passwd * pw = getpwuid(${uid}); + if (NULL == pw) { + perror("getpwuid()"); + return EXIT_FAILURE; + } + + if (NULL != pw->pw_dir) { + rc = chdir(pw->pw_dir); + if (0 != rc) { + rc = chdir("/"); + } + } else { + rc = chdir("/"); + } + if (0 != rc) { + perror("chdir()"); + return EXIT_FAILURE; + } + } + + argv[0] = "${command}"; + execv(argv[0], argv); + + perror("execv()"); + return EXIT_FAILURE; + } + ''; + in pkgs.runCommand name {} "gcc -Wall -Wextra -Werror -std=gnu99 -O2 ${src} -o $out"; + + cliapp = submodule({name, ...}: + { + options = { + user = mkOption { + description = '' + User (and group) to run as. Only users in this group can execute + this application. + ''; + type = str; + default = name; + }; + command = mkOption { + description = "Path to executable"; + type = path; + }; + }; + }); + +in { + options.nixsap = { + apps.cli = mkOption { + description = '' + Command line applications that should run as other users and likely + have special privileges, e. g. to access secret keys. This is + implemented with setuid-wrappers. Each wrapper is launched as root, + immediately switches to specified user, then executes something + useful. This is like sudo, but access is controlled via wrapper's + group: only users in wrapper's group can execute the wrapper. + + Starting as set-uid-non-root is not sufficient, because we might + need supplementary groups, like "keys". + ''; + type = attrsOf cliapp; + default = {}; + }; + }; + + config = { + nixsap.system.users.daemons = unique (mapAttrsToList (_: a: a.user) apps); + security.setuidOwners = mapAttrsToList (n: a: + { program = n; + owner = "root"; + group = a.user; + setuid = true; + setgid = false; + permissions = "u+rx,g+x,o="; + source = exec n a; + }) apps; + }; +} + -- cgit v1.2.3