]> andersk Git - moira.git/blob - gen/acl.pc
35942a612f0335447dd3810ea501245a0a8a7c22
[moira.git] / gen / acl.pc
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, 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];
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           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               else if (!strcasecmp(kind, "userlist"))
119                 dump_user_list(out, "LIST", lid);
120             }
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
133 void dump_access_file(FILE *out, int lid)
134 {
135   struct save_queue *sq = get_acl("LIST", lid, merge_access_bits);
136   struct imember *m;
137   char *name, *lasts = NULL;
138   int i = 0;
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         }
150       else if (m->type == 'K')
151         {
152           name = strtok_r(m->name, "@", &lasts);
153           EXEC SQL SELECT count(login) INTO :i FROM users 
154             WHERE login = :name and status != 3;
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         }
163       freeimember(m);
164     }
165   sq_destroy(sq);
166 }
167
168 char *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
211 void 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;
216   char starbits[8] = { 0 };
217   int num;
218
219   num = 0;
220   while (sq_get_data(sq, &m))
221     {
222       if (m->type != 'S' || !strcmp(m->name, "*"))
223         num++;
224     }
225
226   fprintf(out, "%d\n", num);
227   while (sq_remove_data(sq, &m))
228     {
229       bits = merge_discuss_acls(m->tag, "");
230       if (m->type != 'S')
231         {
232           canon_krb(m, 4, name, sizeof(name));
233           fprintf(out, "%s:%s\n", bits, name);
234         }
235       else if (!strcmp(m->name, "*"))
236         strcpy(starbits, bits);
237       free(bits);
238       freeimember(m);
239     }
240   sq_destroy(sq);
241
242   /* Discuss ACLs are ordered, so "*" must come last. */
243   if (*starbits)
244     fprintf(out, "%s:*\n", starbits);
245 }
246
247 char *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
262 void 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];
270   int uid, i = 0;
271   char *name, *n, *lasts = NULL;
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;
299
300         case 'K':
301           name = strtok_r(m->name, "@", &lasts);
302             
303           EXEC SQL SELECT count(login) INTO :i FROM users WHERE 
304             login = :name and status != 3;
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;
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  */
335 void dump_group_file(FILE *out, int id)
336 {
337   EXEC SQL BEGIN DECLARE SECTION;
338   int lid = id, mid, gid, grouplist, i = 0;
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;
343   char *maybecomma, *s, *n, *lasts = NULL;
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                 }
377               else if (m->type == 'K')
378                 {
379                   n = strtok_r(m->name, "@", &lasts);
380                   EXEC SQL SELECT count(login) INTO :i FROM users
381                     WHERE login = :n and status != 3;
382                   if (i == 1)
383                     {
384                       fprintf(out, "%s%s", maybecomma, n);
385                       maybecomma = ",";
386                     }
387                 }
388               freeimember(m);
389             }
390           fprintf(out, "\n");
391           sq_destroy(sq);
392           break;
393         }
394     }
395   EXEC SQL CLOSE csr_grp;
396 }
397
398 void sqlerr(void)
399 {
400   db_error(sqlca.sqlcode);
401   exit(MR_DBMS_ERR);
402 }
This page took 0.054471 seconds and 3 git commands to generate.