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