/* Copyright (C) 2006 West Consulting Copyright (C) 2006-2015 Arthur de Jong Copyright (C) 2015-2016 Luke Shumaker 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 /* for dlopen(3), dlsym(3), and dlerror(3) */ #include /* for errno */ #include /* for getpwnam(3) */ #include /* for printf(3) and fprintf(3) */ #include /* for strerror(3) */ #include /* for 'struct passwd' and 'struct group' */ #include /* for SD_{WARNING,DEBUG} */ #include /* 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; }