]> andersk Git - moira.git/blame - gen/acl.pc
make DISCUSS-type acls owned by user discuss.
[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);
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
131void 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
151char *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
194void 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
230char *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
245void 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 */
291void 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
343void sqlerr(void)
344{
345 db_error(sqlca.sqlcode);
346 exit(MR_DBMS_ERR);
347}
This page took 0.096453 seconds and 5 git commands to generate.