]>
Commit | Line | Data |
---|---|---|
883e2e2b | 1 | /* $Id$ |
2 | * | |
3 | * This generates acl files for various servers. | |
4 | * | |
5 | * Copyright (C) 1999 by the Massachusetts Institute of Technology. | |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
8 | */ | |
9 | ||
10 | #include <mit-copyright.h> | |
11 | #include <moira.h> | |
12 | #include <moira_site.h> | |
13 | #include "util.h" | |
14 | ||
15 | #include <sys/stat.h> | |
16 | #include <sys/types.h> | |
17 | ||
18 | #include <stdio.h> | |
19 | #include <stdlib.h> | |
20 | #include <string.h> | |
21 | ||
22 | #include <krb.h> | |
23 | ||
24 | EXEC SQL INCLUDE sqlca; | |
25 | ||
26 | RCSID("$Header$"); | |
27 | ||
28 | char *whoami = "acl.gen"; | |
29 | char *db = "moira/moira"; | |
30 | char defaultrealm[REALM_SZ]; | |
31 | ||
32 | void dump_access_file(FILE *out, int lid); | |
33 | char *merge_access_bits(char *t1, char *t2); | |
34 | void dump_discuss_acl(FILE *out, int lid); | |
35 | void dump_passwd_file(FILE *out, int lid); | |
36 | void dump_group_file(FILE *out, int id); | |
37 | char *merge_discuss_acls(char *one, char *two); | |
38 | void sqlerr(void); | |
39 | ||
40 | int main(int argc, char **argv) | |
41 | { | |
42 | EXEC SQL BEGIN DECLARE SECTION; | |
5904ab19 | 43 | int mid, lid, discuss_uid = -1; |
883e2e2b | 44 | char target[ACL_TARGET_SIZE], kind[ACL_KIND_SIZE]; |
45 | char host[MACHINE_NAME_SIZE]; | |
46 | EXEC SQL END DECLARE SECTION; | |
47 | char filename[MAXPATHLEN]; | |
48 | TARFILE *tf; | |
49 | FILE *out; | |
50 | struct save_queue *sq; | |
51 | time_t now = time(NULL); | |
52 | ||
53 | EXEC SQL WHENEVER SQLERROR DO sqlerr(); | |
54 | EXEC SQL CONNECT :db; | |
55 | init_acls(); | |
56 | ||
57 | EXEC SQL DECLARE csr_mach CURSOR FOR | |
58 | SELECT UNIQUE mach_id FROM acl; | |
59 | EXEC SQL OPEN csr_mach; | |
60 | while (1) | |
61 | { | |
62 | EXEC SQL FETCH csr_mach INTO :mid; | |
63 | if (sqlca.sqlcode) | |
64 | break; | |
65 | ||
66 | EXEC SQL SELECT name INTO :host FROM machine | |
67 | WHERE mach_id = :mid; | |
68 | if (sqlca.sqlcode) | |
69 | continue; | |
70 | strtrim(host); | |
71 | ||
72 | sprintf(filename, "%s/acl/%s", DCM_DIR, host); | |
73 | tf = tarfile_open(filename); | |
74 | ||
75 | EXEC SQL DECLARE csr_acl CURSOR FOR | |
76 | SELECT target, kind, list_id | |
77 | FROM acl | |
78 | WHERE mach_id = :mid; | |
79 | EXEC SQL OPEN csr_acl; | |
80 | while (1) | |
81 | { | |
82 | EXEC SQL FETCH csr_acl INTO :target, :kind, :lid; | |
83 | if (sqlca.sqlcode) | |
84 | break; | |
85 | ||
86 | strtrim(target); | |
87 | strtrim(kind); | |
88 | ||
5904ab19 | 89 | if (!strcasecmp(kind, "discuss")) |
90 | { | |
91 | /* Discuss acls need to be owned by discuss. */ | |
92 | if (discuss_uid == -1) | |
93 | { | |
94 | EXEC SQL SELECT unix_uid INTO :discuss_uid | |
95 | FROM users WHERE login = 'discuss'; | |
96 | } | |
97 | out = tarfile_start(tf, target, 0644, discuss_uid, 1, | |
98 | "discuss", "daemon", now); | |
99 | dump_discuss_acl(out, lid); | |
100 | } | |
101 | else | |
102 | { | |
103 | /* Otherwise own by root? Perhaps the acl table should | |
104 | * say, really... | |
105 | */ | |
106 | out = tarfile_start(tf, target, 0644, 0, 0, "root", "root", now); | |
107 | ||
108 | if (!strcasecmp(kind, "kerberos4")) | |
109 | dump_krb_acl(out, "LIST", lid, 4); | |
110 | else if (!strcasecmp(kind, "kerberos5")) | |
111 | dump_krb_acl(out, "LIST", lid, 5); | |
112 | else if (!strcasecmp(kind, "access")) | |
113 | dump_access_file(out, lid); | |
114 | else if (!strcasecmp(kind, "passwd")) | |
115 | dump_passwd_file(out, lid); | |
116 | else if (!strcasecmp(kind, "group")) | |
117 | dump_group_file(out, lid); | |
458b64a1 | 118 | else if (!strcasecmp(kind, "userlist")) |
119 | dump_user_list(out, "LIST", lid); | |
5904ab19 | 120 | } |
883e2e2b | 121 | |
122 | tarfile_end(tf); | |
123 | } | |
124 | ||
125 | tarfile_close(tf); | |
126 | } | |
127 | ||
128 | EXEC SQL COMMIT RELEASE; | |
129 | ||
130 | exit(MR_SUCCESS); | |
131 | } | |
132 | ||
133 | void dump_access_file(FILE *out, int lid) | |
134 | { | |
135 | struct save_queue *sq = get_acl("LIST", lid, merge_access_bits); | |
136 | struct imember *m; | |
39fa010c | 137 | char *name, *lasts = NULL; |
138 | int i = 0; | |
883e2e2b | 139 | |
140 | while (sq_remove_data(sq, &m)) | |
141 | { | |
142 | if (m->type == 'U' || | |
143 | (m->type == 'S' && m->name[0] == '*')) | |
144 | { | |
145 | if (*(m->tag)) | |
146 | fprintf(out, "%-10s %s\n", m->name, m->tag); | |
147 | else | |
148 | fprintf(out, "%-10s rl\n", m->name); | |
149 | } | |
39fa010c | 150 | else if (m->type == 'K') |
151 | { | |
152 | name = strtok_r(m->name, "@", &lasts); | |
153 | EXEC SQL SELECT count(login) INTO :i FROM users | |
f5da21ba | 154 | WHERE login = :name and status != 3; |
39fa010c | 155 | if (i == 1) |
156 | { | |
157 | if (*(m->tag)) | |
158 | fprintf(out, "%-10s %s\n", m->name, m->tag); | |
159 | else | |
160 | fprintf(out, "%-10s rl\n", m->name); | |
161 | } | |
162 | } | |
883e2e2b | 163 | freeimember(m); |
164 | } | |
165 | sq_destroy(sq); | |
166 | } | |
167 | ||
168 | char *merge_access_bits(char *t1, char *t2) | |
169 | { | |
170 | char *m = NULL, *ans; | |
171 | int r = 1, l = 1; | |
172 | ||
173 | /* Clear bits that aren't granted by both tags. */ | |
174 | if ((*t1 && t1[0] != 'r' && t1[1] != 'r') || | |
175 | (*t2 && t2[0] != 'r' && t2[1] != 'r')) | |
176 | r = 0; | |
177 | if ((*t1 && t1[0] != 'l' && t1[1] != 'l') || | |
178 | (*t2 && t2[0] != 'l' && t2[1] != 'l')) | |
179 | l = 0; | |
180 | ||
181 | if (!r || !l) | |
182 | { | |
183 | /* Skip to message part of tag 1 */ | |
184 | m = t1; | |
185 | while (*m && !isspace(*m)) | |
186 | m++; | |
187 | while (isspace(*m)) | |
188 | m++; | |
189 | ||
190 | /* If nothing there, skip to message part of tag 2 */ | |
191 | if (!*m) | |
192 | { | |
193 | m = t2; | |
194 | while (*m && !isspace(*m)) | |
195 | m++; | |
196 | while (isspace(*m)) | |
197 | m++; | |
198 | } | |
199 | ||
200 | ans = malloc(4 + strlen(m)); | |
201 | sprintf(ans, "%c %s", r ? 'r' : l ? 'l' : '-', m); | |
202 | } | |
203 | else | |
204 | { | |
205 | ans = malloc(3); | |
206 | strcpy(ans, "rl"); | |
207 | } | |
208 | return ans; | |
209 | } | |
210 | ||
211 | void dump_discuss_acl(FILE *out, int lid) | |
212 | { | |
213 | struct save_queue *sq = get_acl("LIST", lid, merge_discuss_acls); | |
214 | struct imember *m; | |
215 | char name[STRINGS_STRING_SIZE], *bits; | |
5904ab19 | 216 | char starbits[8] = { 0 }; |
883e2e2b | 217 | int num; |
218 | ||
219 | num = 0; | |
220 | while (sq_get_data(sq, &m)) | |
5904ab19 | 221 | { |
222 | if (m->type != 'S' || !strcmp(m->name, "*")) | |
223 | num++; | |
224 | } | |
883e2e2b | 225 | |
226 | fprintf(out, "%d\n", num); | |
227 | while (sq_remove_data(sq, &m)) | |
228 | { | |
5904ab19 | 229 | bits = merge_discuss_acls(m->tag, ""); |
883e2e2b | 230 | if (m->type != 'S') |
231 | { | |
232 | canon_krb(m, 4, name, sizeof(name)); | |
5904ab19 | 233 | fprintf(out, "%s:%s\n", bits, name); |
883e2e2b | 234 | } |
5904ab19 | 235 | else if (!strcmp(m->name, "*")) |
236 | strcpy(starbits, bits); | |
237 | free(bits); | |
883e2e2b | 238 | freeimember(m); |
239 | } | |
240 | sq_destroy(sq); | |
5904ab19 | 241 | |
242 | /* Discuss ACLs are ordered, so "*" must come last. */ | |
243 | if (*starbits) | |
244 | fprintf(out, "%s:*\n", starbits); | |
883e2e2b | 245 | } |
246 | ||
247 | char *merge_discuss_acls(char *one, char *two) | |
248 | { | |
249 | char bits[8]; | |
250 | ||
251 | sprintf(bits, "%c%c%c%c%c%c%c", | |
252 | strchr(one, 'a') || strchr(two, 'a') ? 'a' : ' ', | |
253 | strchr(one, 'c') || strchr(two, 'c') ? 'c' : ' ', | |
254 | strchr(one, 'd') || strchr(two, 'd') ? 'd' : ' ', | |
255 | strchr(one, 'o') || strchr(two, 'o') ? 'o' : ' ', | |
256 | strchr(one, 'r') || strchr(two, 'r') ? 'r' : ' ', | |
257 | strchr(one, 's') || strchr(two, 's') ? 's' : ' ', | |
258 | strchr(one, 'w') || strchr(two, 'w') ? 'w' : ' '); | |
259 | return strdup(bits); | |
260 | } | |
261 | ||
262 | void dump_passwd_file(FILE *out, int lid) | |
263 | { | |
264 | struct save_queue *sq = get_acl("LIST", lid, NULL); | |
265 | struct imember *m; | |
266 | EXEC SQL BEGIN DECLARE SECTION; | |
267 | char shell[USERS_SHELL_SIZE], fullname[USERS_FULLNAME_SIZE]; | |
268 | char nickname[USERS_NICKNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE]; | |
269 | char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE]; | |
39fa010c | 270 | int uid, i = 0; |
271 | char *name, *n, *lasts = NULL; | |
883e2e2b | 272 | EXEC SQL END DECLARE SECTION; |
273 | ||
274 | while (sq_remove_data(sq, &m)) | |
275 | { | |
276 | switch (m->type) | |
277 | { | |
278 | case 'U': | |
279 | name = m->name; | |
280 | ||
281 | EXEC SQL SELECT unix_uid, shell, fullname, nickname, | |
282 | office_addr, office_phone, home_phone | |
283 | INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp | |
284 | FROM users | |
285 | WHERE login = :name AND status != 3; | |
286 | if (sqlca.sqlcode) | |
287 | continue; | |
288 | ||
289 | strtrim(shell); | |
290 | strtrim(fullname); | |
291 | strtrim(nickname); | |
292 | strtrim(op); | |
293 | strtrim(oa); | |
294 | strtrim(hp); | |
295 | ||
296 | fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n", | |
297 | name, uid, fullname, nickname, oa, op, hp, name, shell); | |
298 | break; | |
39fa010c | 299 | |
300 | case 'K': | |
301 | name = strtok_r(m->name, "@", &lasts); | |
302 | ||
303 | EXEC SQL SELECT count(login) INTO :i FROM users WHERE | |
f5da21ba | 304 | login = :name and status != 3; |
39fa010c | 305 | if (i == 1) |
306 | { | |
307 | EXEC SQL SELECT unix_uid, shell, fullname, nickname, | |
308 | office_addr, office_phone, home_phone | |
309 | INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp | |
310 | FROM users | |
311 | WHERE login = :name AND status != 3; | |
312 | if (sqlca.sqlcode) | |
313 | continue; | |
314 | ||
315 | strtrim(shell); | |
316 | strtrim(fullname); | |
317 | strtrim(nickname); | |
318 | strtrim(op); | |
319 | strtrim(oa); | |
320 | strtrim(hp); | |
321 | ||
322 | fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n", | |
323 | name, uid, fullname, nickname, oa, op, hp, name, shell); | |
324 | } | |
325 | break; | |
883e2e2b | 326 | } |
327 | freeimember(m); | |
328 | } | |
329 | sq_destroy(sq); | |
330 | } | |
331 | ||
332 | /* This one is a bit weird since we actually look at top-level | |
333 | * lists rather then flattening them. | |
334 | */ | |
335 | void dump_group_file(FILE *out, int id) | |
336 | { | |
337 | EXEC SQL BEGIN DECLARE SECTION; | |
39fa010c | 338 | int lid = id, mid, gid, grouplist, i = 0; |
883e2e2b | 339 | char mtype[IMEMBERS_MEMBER_TYPE_SIZE], name[LIST_NAME_SIZE]; |
340 | EXEC SQL END DECLARE SECTION; | |
341 | struct save_queue *sq; | |
342 | struct imember *m; | |
39fa010c | 343 | char *maybecomma, *s, *n, *lasts = NULL; |
883e2e2b | 344 | |
345 | EXEC SQL DECLARE csr_grp CURSOR FOR | |
346 | SELECT member_type, member_id FROM imembers | |
347 | WHERE list_id = :lid AND direct = 1; | |
348 | EXEC SQL OPEN csr_grp; | |
349 | while (1) | |
350 | { | |
351 | EXEC SQL FETCH csr_grp INTO :mtype, :mid; | |
352 | if (sqlca.sqlcode) | |
353 | break; | |
354 | ||
355 | switch (*mtype) | |
356 | { | |
357 | case 'L': | |
358 | EXEC SQL SELECT name, gid, grouplist | |
359 | INTO :name, :gid, :grouplist | |
360 | FROM list | |
361 | WHERE list_id = :mid; | |
362 | if (sqlca.sqlcode || !grouplist) | |
363 | break; | |
364 | ||
365 | strtrim(name); | |
366 | ||
367 | fprintf(out, "%s:*:%d:", name, gid); | |
368 | sq = get_acl("LIST", mid, NULL); | |
369 | maybecomma = ""; | |
370 | while (sq_remove_data(sq, &m)) | |
371 | { | |
372 | if (m->type == 'U') | |
373 | { | |
374 | fprintf(out, "%s%s", maybecomma, m->name); | |
375 | maybecomma = ","; | |
376 | } | |
39fa010c | 377 | else if (m->type == 'K') |
378 | { | |
379 | n = strtok_r(m->name, "@", &lasts); | |
380 | EXEC SQL SELECT count(login) INTO :i FROM users | |
f5da21ba | 381 | WHERE login = :n and status != 3; |
39fa010c | 382 | if (i == 1) |
383 | { | |
384 | fprintf(out, "%s%s", maybecomma, n); | |
385 | maybecomma = ","; | |
386 | } | |
387 | } | |
883e2e2b | 388 | freeimember(m); |
389 | } | |
390 | fprintf(out, "\n"); | |
391 | sq_destroy(sq); | |
392 | break; | |
393 | } | |
394 | } | |
395 | EXEC SQL CLOSE csr_grp; | |
396 | } | |
397 | ||
398 | void sqlerr(void) | |
399 | { | |
400 | db_error(sqlca.sqlcode); | |
401 | exit(MR_DBMS_ERR); | |
402 | } |