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