1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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;
}
|