]>
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); | |
118 | } | |
883e2e2b | 119 | |
120 | tarfile_end(tf); | |
121 | } | |
122 | ||
123 | tarfile_close(tf); | |
124 | } | |
125 | ||
126 | EXEC SQL COMMIT RELEASE; | |
127 | ||
128 | exit(MR_SUCCESS); | |
129 | } | |
130 | ||
131 | void dump_access_file(FILE *out, int lid) | |
132 | { | |
133 | struct save_queue *sq = get_acl("LIST", lid, merge_access_bits); | |
134 | struct imember *m; | |
135 | ||
136 | while (sq_remove_data(sq, &m)) | |
137 | { | |
138 | if (m->type == 'U' || | |
139 | (m->type == 'S' && m->name[0] == '*')) | |
140 | { | |
141 | if (*(m->tag)) | |
142 | fprintf(out, "%-10s %s\n", m->name, m->tag); | |
143 | else | |
144 | fprintf(out, "%-10s rl\n", m->name); | |
145 | } | |
146 | freeimember(m); | |
147 | } | |
148 | sq_destroy(sq); | |
149 | } | |
150 | ||
151 | char *merge_access_bits(char *t1, char *t2) | |
152 | { | |
153 | char *m = NULL, *ans; | |
154 | int r = 1, l = 1; | |
155 | ||
156 | /* Clear bits that aren't granted by both tags. */ | |
157 | if ((*t1 && t1[0] != 'r' && t1[1] != 'r') || | |
158 | (*t2 && t2[0] != 'r' && t2[1] != 'r')) | |
159 | r = 0; | |
160 | if ((*t1 && t1[0] != 'l' && t1[1] != 'l') || | |
161 | (*t2 && t2[0] != 'l' && t2[1] != 'l')) | |
162 | l = 0; | |
163 | ||
164 | if (!r || !l) | |
165 | { | |
166 | /* Skip to message part of tag 1 */ | |
167 | m = t1; | |
168 | while (*m && !isspace(*m)) | |
169 | m++; | |
170 | while (isspace(*m)) | |
171 | m++; | |
172 | ||
173 | /* If nothing there, skip to message part of tag 2 */ | |
174 | if (!*m) | |
175 | { | |
176 | m = t2; | |
177 | while (*m && !isspace(*m)) | |
178 | m++; | |
179 | while (isspace(*m)) | |
180 | m++; | |
181 | } | |
182 | ||
183 | ans = malloc(4 + strlen(m)); | |
184 | sprintf(ans, "%c %s", r ? 'r' : l ? 'l' : '-', m); | |
185 | } | |
186 | else | |
187 | { | |
188 | ans = malloc(3); | |
189 | strcpy(ans, "rl"); | |
190 | } | |
191 | return ans; | |
192 | } | |
193 | ||
194 | void dump_discuss_acl(FILE *out, int lid) | |
195 | { | |
196 | struct save_queue *sq = get_acl("LIST", lid, merge_discuss_acls); | |
197 | struct imember *m; | |
198 | char name[STRINGS_STRING_SIZE], *bits; | |
5904ab19 | 199 | char starbits[8] = { 0 }; |
883e2e2b | 200 | int num; |
201 | ||
202 | num = 0; | |
203 | while (sq_get_data(sq, &m)) | |
5904ab19 | 204 | { |
205 | if (m->type != 'S' || !strcmp(m->name, "*")) | |
206 | num++; | |
207 | } | |
883e2e2b | 208 | |
209 | fprintf(out, "%d\n", num); | |
210 | while (sq_remove_data(sq, &m)) | |
211 | { | |
5904ab19 | 212 | bits = merge_discuss_acls(m->tag, ""); |
883e2e2b | 213 | if (m->type != 'S') |
214 | { | |
215 | canon_krb(m, 4, name, sizeof(name)); | |
5904ab19 | 216 | fprintf(out, "%s:%s\n", bits, name); |
883e2e2b | 217 | } |
5904ab19 | 218 | else if (!strcmp(m->name, "*")) |
219 | strcpy(starbits, bits); | |
220 | free(bits); | |
883e2e2b | 221 | freeimember(m); |
222 | } | |
223 | sq_destroy(sq); | |
5904ab19 | 224 | |
225 | /* Discuss ACLs are ordered, so "*" must come last. */ | |
226 | if (*starbits) | |
227 | fprintf(out, "%s:*\n", starbits); | |
883e2e2b | 228 | } |
229 | ||
230 | char *merge_discuss_acls(char *one, char *two) | |
231 | { | |
232 | char bits[8]; | |
233 | ||
234 | sprintf(bits, "%c%c%c%c%c%c%c", | |
235 | strchr(one, 'a') || strchr(two, 'a') ? 'a' : ' ', | |
236 | strchr(one, 'c') || strchr(two, 'c') ? 'c' : ' ', | |
237 | strchr(one, 'd') || strchr(two, 'd') ? 'd' : ' ', | |
238 | strchr(one, 'o') || strchr(two, 'o') ? 'o' : ' ', | |
239 | strchr(one, 'r') || strchr(two, 'r') ? 'r' : ' ', | |
240 | strchr(one, 's') || strchr(two, 's') ? 's' : ' ', | |
241 | strchr(one, 'w') || strchr(two, 'w') ? 'w' : ' '); | |
242 | return strdup(bits); | |
243 | } | |
244 | ||
245 | void dump_passwd_file(FILE *out, int lid) | |
246 | { | |
247 | struct save_queue *sq = get_acl("LIST", lid, NULL); | |
248 | struct imember *m; | |
249 | EXEC SQL BEGIN DECLARE SECTION; | |
250 | char shell[USERS_SHELL_SIZE], fullname[USERS_FULLNAME_SIZE]; | |
251 | char nickname[USERS_NICKNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE]; | |
252 | char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE]; | |
253 | int uid; | |
254 | char *name; | |
255 | EXEC SQL END DECLARE SECTION; | |
256 | ||
257 | while (sq_remove_data(sq, &m)) | |
258 | { | |
259 | switch (m->type) | |
260 | { | |
261 | case 'U': | |
262 | name = m->name; | |
263 | ||
264 | EXEC SQL SELECT unix_uid, shell, fullname, nickname, | |
265 | office_addr, office_phone, home_phone | |
266 | INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp | |
267 | FROM users | |
268 | WHERE login = :name AND status != 3; | |
269 | if (sqlca.sqlcode) | |
270 | continue; | |
271 | ||
272 | strtrim(shell); | |
273 | strtrim(fullname); | |
274 | strtrim(nickname); | |
275 | strtrim(op); | |
276 | strtrim(oa); | |
277 | strtrim(hp); | |
278 | ||
279 | fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n", | |
280 | name, uid, fullname, nickname, oa, op, hp, name, shell); | |
281 | break; | |
282 | } | |
283 | freeimember(m); | |
284 | } | |
285 | sq_destroy(sq); | |
286 | } | |
287 | ||
288 | /* This one is a bit weird since we actually look at top-level | |
289 | * lists rather then flattening them. | |
290 | */ | |
291 | void dump_group_file(FILE *out, int id) | |
292 | { | |
293 | EXEC SQL BEGIN DECLARE SECTION; | |
294 | int lid = id, mid, gid, grouplist; | |
295 | char mtype[IMEMBERS_MEMBER_TYPE_SIZE], name[LIST_NAME_SIZE]; | |
296 | EXEC SQL END DECLARE SECTION; | |
297 | struct save_queue *sq; | |
298 | struct imember *m; | |
299 | char *maybecomma, *s; | |
300 | ||
301 | EXEC SQL DECLARE csr_grp CURSOR FOR | |
302 | SELECT member_type, member_id FROM imembers | |
303 | WHERE list_id = :lid AND direct = 1; | |
304 | EXEC SQL OPEN csr_grp; | |
305 | while (1) | |
306 | { | |
307 | EXEC SQL FETCH csr_grp INTO :mtype, :mid; | |
308 | if (sqlca.sqlcode) | |
309 | break; | |
310 | ||
311 | switch (*mtype) | |
312 | { | |
313 | case 'L': | |
314 | EXEC SQL SELECT name, gid, grouplist | |
315 | INTO :name, :gid, :grouplist | |
316 | FROM list | |
317 | WHERE list_id = :mid; | |
318 | if (sqlca.sqlcode || !grouplist) | |
319 | break; | |
320 | ||
321 | strtrim(name); | |
322 | ||
323 | fprintf(out, "%s:*:%d:", name, gid); | |
324 | sq = get_acl("LIST", mid, NULL); | |
325 | maybecomma = ""; | |
326 | while (sq_remove_data(sq, &m)) | |
327 | { | |
328 | if (m->type == 'U') | |
329 | { | |
330 | fprintf(out, "%s%s", maybecomma, m->name); | |
331 | maybecomma = ","; | |
332 | } | |
333 | freeimember(m); | |
334 | } | |
335 | fprintf(out, "\n"); | |
336 | sq_destroy(sq); | |
337 | break; | |
338 | } | |
339 | } | |
340 | EXEC SQL CLOSE csr_grp; | |
341 | } | |
342 | ||
343 | void sqlerr(void) | |
344 | { | |
345 | db_error(sqlca.sqlcode); | |
346 | exit(MR_DBMS_ERR); | |
347 | } |