1 |
douglas |
603 |
// CCS Computer Science |
2 |
douglas |
597 |
// Admin |
3 |
|
|
// |
4 |
|
|
// Douglas Thrift |
5 |
|
|
// |
6 |
|
|
// $Id$ |
7 |
|
|
|
8 |
|
|
#if !defined(__FreeBSD__) && !defined(__sun__) && !defined(__APPLE__) |
9 |
|
|
# ifndef _BSD_SOURCE |
10 |
|
|
# define _BSD_SOURCE |
11 |
|
|
# endif |
12 |
douglas |
652 |
# include <bsd/string.h> |
13 |
|
|
#else |
14 |
|
|
# include <string.h> |
15 |
douglas |
597 |
#endif |
16 |
|
|
|
17 |
|
|
#include <assert.h> |
18 |
|
|
#include <libgen.h> |
19 |
|
|
#include <setjmp.h> |
20 |
|
|
#include <stdio.h> |
21 |
|
|
#include <stdlib.h> |
22 |
|
|
#include <unistd.h> |
23 |
|
|
#include <sys/types.h> |
24 |
|
|
#include <pwd.h> |
25 |
|
|
|
26 |
|
|
#define LDAP_DEPRECATED 1 |
27 |
|
|
|
28 |
|
|
#include <ldap.h> |
29 |
|
|
|
30 |
|
|
#define EXCEPTION 1 |
31 |
|
|
#define POSIX_EXCEPTION 2 |
32 |
|
|
|
33 |
|
|
static char *exception; |
34 |
|
|
|
35 |
|
|
static inline int posix_check(int value, jmp_buf environment) |
36 |
|
|
{ |
37 |
|
|
if (value == -1) |
38 |
|
|
longjmp(environment, POSIX_EXCEPTION); |
39 |
|
|
|
40 |
|
|
return value; |
41 |
|
|
} |
42 |
|
|
|
43 |
|
|
static inline int ldap_check(int value, jmp_buf environment) |
44 |
|
|
{ |
45 |
|
|
if (value != LDAP_SUCCESS) |
46 |
|
|
longjmp(environment, (exception = ldap_err2string(value), EXCEPTION)); |
47 |
|
|
|
48 |
|
|
return value; |
49 |
|
|
} |
50 |
|
|
|
51 |
|
|
int main(int argc, char *argv[]) |
52 |
|
|
{ |
53 |
|
|
if (argc < 1) |
54 |
|
|
return 1; |
55 |
|
|
|
56 |
|
|
jmp_buf environment; |
57 |
|
|
|
58 |
|
|
switch (setjmp(environment)) |
59 |
|
|
{ |
60 |
|
|
case 0: |
61 |
|
|
break; |
62 |
|
|
case EXCEPTION: |
63 |
|
|
fprintf(stderr, "%s: %s\n", argv[0], exception); |
64 |
|
|
|
65 |
|
|
return 1; |
66 |
|
|
case POSIX_EXCEPTION: |
67 |
|
|
perror(argv[0]); |
68 |
|
|
|
69 |
|
|
return 1; |
70 |
|
|
} |
71 |
|
|
|
72 |
|
|
char _program[strlen(argv[0])]; |
73 |
|
|
|
74 |
|
|
strcpy(_program, argv[0]); |
75 |
|
|
|
76 |
|
|
char *program = basename(_program), *programs[] = { "adduser", "chfn", "chsh", "passwd" }; |
77 |
|
|
LDAP *ldap; |
78 |
|
|
|
79 |
|
|
if (!program) |
80 |
|
|
longjmp(environment, POSIX_EXCEPTION); |
81 |
|
|
|
82 |
|
|
for (int index = 0; index != sizeof (programs) / sizeof (*programs); ++index) |
83 |
|
|
if (!strcmp(program, programs[index])) |
84 |
|
|
goto go; |
85 |
|
|
|
86 |
|
|
fprintf(stderr, "%s: Unknown command: %s.\n", argv[0], program); |
87 |
|
|
|
88 |
|
|
return 1; |
89 |
|
|
|
90 |
douglas |
600 |
go: if (ldap_initialize(&ldap, MASTER_URI " " SLAVE_URI) != LDAP_SUCCESS) |
91 |
douglas |
597 |
longjmp(environment, POSIX_EXCEPTION); |
92 |
|
|
|
93 |
|
|
int version = LDAP_VERSION3, demand = LDAP_OPT_X_TLS_DEMAND; |
94 |
|
|
|
95 |
|
|
assert(ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS); |
96 |
|
|
assert(ldap_set_option(ldap, LDAP_OPT_X_TLS_CACERTFILE, "/ccs/ssl/ccscert.pem") == LDAP_OPT_SUCCESS); |
97 |
|
|
assert(ldap_set_option(ldap, LDAP_OPT_X_TLS_REQUIRE_CERT, &demand) == LDAP_OPT_SUCCESS); |
98 |
|
|
|
99 |
|
|
uid_t uid = getuid(); |
100 |
|
|
struct passwd *entry = getpwuid(uid); |
101 |
|
|
|
102 |
|
|
if (!entry) |
103 |
|
|
longjmp(environment, POSIX_EXCEPTION); |
104 |
|
|
|
105 |
|
|
size_t length = strlen(entry->pw_name); |
106 |
douglas |
600 |
char user[length + 1], dn[length + 5 + sizeof (PEOPLE)], prompt[length + 16]; |
107 |
douglas |
597 |
|
108 |
|
|
strlcpy(user, entry->pw_name, sizeof (user)); |
109 |
douglas |
600 |
snprintf(dn, sizeof (dn), "uid=%s," PEOPLE, user); |
110 |
douglas |
597 |
snprintf(prompt, sizeof (prompt), "Password for %s: ", user); |
111 |
|
|
|
112 |
|
|
char *password = getpass(prompt); |
113 |
|
|
|
114 |
douglas |
603 |
posix_check(unsetenv("LD_LIBRARY_PATH"), environment); |
115 |
|
|
posix_check(setuid(geteuid()), environment); |
116 |
douglas |
597 |
ldap_check(ldap_simple_bind_s(ldap, dn, password), environment); |
117 |
douglas |
598 |
ldap_check(ldap_unbind_s(ldap), environment); |
118 |
douglas |
597 |
|
119 |
|
|
if (!strcmp(program, "passwd") && uid != 0) |
120 |
|
|
{ |
121 |
|
|
char old_password[] = "/tmp/old_password.XXXXXX"; |
122 |
|
|
int file = posix_check(mkstemp(old_password), environment); |
123 |
|
|
|
124 |
|
|
posix_check(write(file, password, strlen(password)), environment); |
125 |
|
|
posix_check(close(file), environment); |
126 |
|
|
posix_check(setenv("OLD_PASSWORD", old_password, 1), environment); |
127 |
|
|
} |
128 |
|
|
else |
129 |
|
|
posix_check(unsetenv("OLD_PASSWORD"), environment); |
130 |
|
|
|
131 |
|
|
bzero(password, strlen(password)); |
132 |
|
|
|
133 |
|
|
char python[strlen(program) + 13]; |
134 |
|
|
|
135 |
|
|
snprintf(python, sizeof (python), "/ccs/lib/%s.py", program); |
136 |
|
|
posix_check(setenv("USER", user, 1), environment); |
137 |
|
|
posix_check(unsetenv("PYTHONPATH"), environment); |
138 |
|
|
posix_check(execv(python, argv), environment); |
139 |
|
|
|
140 |
|
|
return 0; |
141 |
|
|
} |