summaryrefslogtreecommitdiff
path: root/bin/nshd-setuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/nshd-setuid.c')
-rw-r--r--bin/nshd-setuid.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/bin/nshd-setuid.c b/bin/nshd-setuid.c
new file mode 100644
index 0000000..aa8847b
--- /dev/null
+++ b/bin/nshd-setuid.c
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2006 West Consulting
+ Copyright (C) 2006-2015 Arthur de Jong
+ Copyright (C) 2015-2016 Luke Shumaker <lukeshu@sbcglobal.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include <dlfcn.h> /* for dlopen(3), dlsym(3), and dlerror(3) */
+#include <errno.h> /* for errno */
+#include <pwd.h> /* for getpwnam(3) */
+#include <stdio.h> /* for printf(3) and fprintf(3) */
+#include <string.h> /* for strerror(3) */
+#include <sys/types.h> /* for 'struct passwd' and 'struct group' */
+#include <systemd/sd-daemon.h> /* for SD_{WARNING,DEBUG} */
+#include <unistd.h> /* for setuid(3), setgid(3), and dup2(3) */
+
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_INVALIDARGUMENT 2
+#define EXIT_NOPERMISSION 4
+
+const char *nss_module_soname = "libnss_ldap.so.2";
+const char *nss_module_sym_version = "_nss_ldap_version";
+const char *nss_module_sym_enablelookups = "_nss_ldap_enablelookups";
+
+static void disable_nss_module(void) {
+ char *err;
+
+ dlerror();
+ void *handle = dlopen(nss_module_soname, RTLD_LAZY | RTLD_NODELETE);
+ err = dlerror();
+ if (handle == NULL) {
+ fprintf(stderr, SD_WARNING "NSS module %s not loaded: %s\n", nss_module_soname, err);
+ return;
+ }
+
+ dlerror();
+ char **version_info = dlsym(handle, nss_module_sym_version);
+ err = dlerror();
+ if ((version_info != NULL) && (err == NULL)) {
+ fprintf(stderr, SD_DEBUG "NSS module %s version %s %s\n", nss_module_soname,
+ version_info[0],
+ version_info[1]);
+ } else {
+ fprintf(stderr, SD_WARNING "NSS module %s version missing: %s\n", nss_module_soname, err);
+ }
+
+ dlerror();
+ int *enable_flag = dlsym(handle, nss_module_sym_enablelookups);
+ err = dlerror();
+ if ((enable_flag == NULL) || (err != NULL)) {
+ fprintf(stderr, SD_WARNING "Unable to disable NSS ldap module for nslcd process: %s\n", err);
+ dlclose(handle);
+ return;
+ }
+ *enable_flag = 0;
+ dlclose(handle);
+}
+
+void usage(char *cmd) {
+ printf("Usage: %s USERNAME COMMAND...\n", cmd);
+ printf("A simple setuid(3) wrapper that runs with the `ldap' NSS module disabled\n");
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 3) {
+ dup2(2, 1);
+ usage(argv[0]);
+ return EXIT_INVALIDARGUMENT;
+ }
+
+ disable_nss_module();
+
+ struct passwd *passwd = getpwnam(argv[1]);
+ if (passwd == NULL) {
+ fprintf(stderr, SD_ERR "Could not look up user: %s\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ if (setgid(passwd->pw_gid) != 0) {
+ fprintf(stderr, SD_ERR "Could not setgid(%lu): %s\n",
+ (unsigned long int)passwd->pw_gid, strerror(errno));
+ return EXIT_NOPERMISSION;
+ }
+ if (setuid(passwd->pw_uid) != 0) {
+ fprintf(stderr, SD_ERR "Could not setuid(%lu): %s\n",
+ (unsigned long int)passwd->pw_gid, strerror(errno));
+ return EXIT_NOPERMISSION;
+ }
+
+ execvp(argv[2], &argv[2]);
+ fprintf(stderr, SD_ERR "Could not exec: %s\n", strerror(errno));
+ return EXIT_FAILURE;
+}