3 * This generates acl files for various servers.
5 * Copyright (C) 1999 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
12 #include <moira_site.h>
16 #include <sys/types.h>
24 EXEC SQL INCLUDE sqlca;
28 char *whoami = "acl.gen";
29 char *db = "moira/moira";
30 char defaultrealm[REALM_SZ];
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);
40 int main(int argc, char **argv)
42 EXEC SQL BEGIN DECLARE SECTION;
43 int mid, lid, discuss_uid = -1;
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];
50 struct save_queue *sq;
51 time_t now = time(NULL);
53 EXEC SQL WHENEVER SQLERROR DO sqlerr();
57 EXEC SQL DECLARE csr_mach CURSOR FOR
58 SELECT UNIQUE mach_id FROM acl;
59 EXEC SQL OPEN csr_mach;
62 EXEC SQL FETCH csr_mach INTO :mid;
66 EXEC SQL SELECT name INTO :host FROM machine
72 sprintf(filename, "%s/acl/%s", DCM_DIR, host);
73 tf = tarfile_open(filename);
75 EXEC SQL DECLARE csr_acl CURSOR FOR
76 SELECT target, kind, list_id
79 EXEC SQL OPEN csr_acl;
82 EXEC SQL FETCH csr_acl INTO :target, :kind, :lid;
89 if (!strcasecmp(kind, "discuss"))
91 /* Discuss acls need to be owned by discuss. */
92 if (discuss_uid == -1)
94 EXEC SQL SELECT unix_uid INTO :discuss_uid
95 FROM users WHERE login = 'discuss';
97 out = tarfile_start(tf, target, 0644, discuss_uid, 1,
98 "discuss", "daemon", now);
99 dump_discuss_acl(out, lid);
103 /* Otherwise own by root? Perhaps the acl table should
106 out = tarfile_start(tf, target, 0644, 0, 0, "root", "root", now);
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);
126 EXEC SQL COMMIT RELEASE;
131 void dump_access_file(FILE *out, int lid)
133 struct save_queue *sq = get_acl("LIST", lid, merge_access_bits);
135 char *name, *lasts = NULL;
138 while (sq_remove_data(sq, &m))
140 if (m->type == 'U' ||
141 (m->type == 'S' && m->name[0] == '*'))
144 fprintf(out, "%-10s %s\n", m->name, m->tag);
146 fprintf(out, "%-10s rl\n", m->name);
148 else if (m->type == 'K')
150 name = strtok_r(m->name, "@", &lasts);
151 EXEC SQL SELECT count(login) INTO :i FROM users
156 fprintf(out, "%-10s %s\n", m->name, m->tag);
158 fprintf(out, "%-10s rl\n", m->name);
166 char *merge_access_bits(char *t1, char *t2)
168 char *m = NULL, *ans;
171 /* Clear bits that aren't granted by both tags. */
172 if ((*t1 && t1[0] != 'r' && t1[1] != 'r') ||
173 (*t2 && t2[0] != 'r' && t2[1] != 'r'))
175 if ((*t1 && t1[0] != 'l' && t1[1] != 'l') ||
176 (*t2 && t2[0] != 'l' && t2[1] != 'l'))
181 /* Skip to message part of tag 1 */
183 while (*m && !isspace(*m))
188 /* If nothing there, skip to message part of tag 2 */
192 while (*m && !isspace(*m))
198 ans = malloc(4 + strlen(m));
199 sprintf(ans, "%c %s", r ? 'r' : l ? 'l' : '-', m);
209 void dump_discuss_acl(FILE *out, int lid)
211 struct save_queue *sq = get_acl("LIST", lid, merge_discuss_acls);
213 char name[STRINGS_STRING_SIZE], *bits;
214 char starbits[8] = { 0 };
218 while (sq_get_data(sq, &m))
220 if (m->type != 'S' || !strcmp(m->name, "*"))
224 fprintf(out, "%d\n", num);
225 while (sq_remove_data(sq, &m))
227 bits = merge_discuss_acls(m->tag, "");
230 canon_krb(m, 4, name, sizeof(name));
231 fprintf(out, "%s:%s\n", bits, name);
233 else if (!strcmp(m->name, "*"))
234 strcpy(starbits, bits);
240 /* Discuss ACLs are ordered, so "*" must come last. */
242 fprintf(out, "%s:*\n", starbits);
245 char *merge_discuss_acls(char *one, char *two)
249 sprintf(bits, "%c%c%c%c%c%c%c",
250 strchr(one, 'a') || strchr(two, 'a') ? 'a' : ' ',
251 strchr(one, 'c') || strchr(two, 'c') ? 'c' : ' ',
252 strchr(one, 'd') || strchr(two, 'd') ? 'd' : ' ',
253 strchr(one, 'o') || strchr(two, 'o') ? 'o' : ' ',
254 strchr(one, 'r') || strchr(two, 'r') ? 'r' : ' ',
255 strchr(one, 's') || strchr(two, 's') ? 's' : ' ',
256 strchr(one, 'w') || strchr(two, 'w') ? 'w' : ' ');
260 void dump_passwd_file(FILE *out, int lid)
262 struct save_queue *sq = get_acl("LIST", lid, NULL);
264 EXEC SQL BEGIN DECLARE SECTION;
265 char shell[USERS_SHELL_SIZE], fullname[USERS_FULLNAME_SIZE];
266 char nickname[USERS_NICKNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE];
267 char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE];
269 char *name, *n, *lasts = NULL;
270 EXEC SQL END DECLARE SECTION;
272 while (sq_remove_data(sq, &m))
279 EXEC SQL SELECT unix_uid, shell, fullname, nickname,
280 office_addr, office_phone, home_phone
281 INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp
283 WHERE login = :name AND status != 3;
294 fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n",
295 name, uid, fullname, nickname, oa, op, hp, name, shell);
299 name = strtok_r(m->name, "@", &lasts);
301 EXEC SQL SELECT count(login) INTO :i FROM users WHERE
305 EXEC SQL SELECT unix_uid, shell, fullname, nickname,
306 office_addr, office_phone, home_phone
307 INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp
309 WHERE login = :name AND status != 3;
320 fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n",
321 name, uid, fullname, nickname, oa, op, hp, name, shell);
330 /* This one is a bit weird since we actually look at top-level
331 * lists rather then flattening them.
333 void dump_group_file(FILE *out, int id)
335 EXEC SQL BEGIN DECLARE SECTION;
336 int lid = id, mid, gid, grouplist, i = 0;
337 char mtype[IMEMBERS_MEMBER_TYPE_SIZE], name[LIST_NAME_SIZE];
338 EXEC SQL END DECLARE SECTION;
339 struct save_queue *sq;
341 char *maybecomma, *s, *n, *lasts = NULL;
343 EXEC SQL DECLARE csr_grp CURSOR FOR
344 SELECT member_type, member_id FROM imembers
345 WHERE list_id = :lid AND direct = 1;
346 EXEC SQL OPEN csr_grp;
349 EXEC SQL FETCH csr_grp INTO :mtype, :mid;
356 EXEC SQL SELECT name, gid, grouplist
357 INTO :name, :gid, :grouplist
359 WHERE list_id = :mid;
360 if (sqlca.sqlcode || !grouplist)
365 fprintf(out, "%s:*:%d:", name, gid);
366 sq = get_acl("LIST", mid, NULL);
368 while (sq_remove_data(sq, &m))
372 fprintf(out, "%s%s", maybecomma, m->name);
375 else if (m->type == 'K')
377 n = strtok_r(m->name, "@", &lasts);
378 EXEC SQL SELECT count(login) INTO :i FROM users
382 fprintf(out, "%s%s", maybecomma, n);
393 EXEC SQL CLOSE csr_grp;
398 db_error(sqlca.sqlcode);