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