]> andersk Git - moira.git/blame - gen/acl.pc
Do something sensible with MACHINE members of lists.
[moira.git] / gen / acl.pc
CommitLineData
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
24EXEC SQL INCLUDE sqlca;
25
26RCSID("$Header$");
27
28char *whoami = "acl.gen";
29char *db = "moira/moira";
30char defaultrealm[REALM_SZ];
31
32void dump_access_file(FILE *out, int lid);
33char *merge_access_bits(char *t1, char *t2);
34void dump_discuss_acl(FILE *out, int lid);
35void dump_passwd_file(FILE *out, int lid);
36void dump_group_file(FILE *out, int id);
37char *merge_discuss_acls(char *one, char *two);
38void sqlerr(void);
39
40int 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
133void 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
168char *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
211void 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
247char *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
262void 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 */
335void 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
398void sqlerr(void)
399{
400 db_error(sqlca.sqlcode);
401 exit(MR_DBMS_ERR);
402}
This page took 0.178119 seconds and 5 git commands to generate.