]> andersk Git - moira.git/blob - gen/acl.pc
Generic acl support.
[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;
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           out = tarfile_start(tf, target, 0644, 0, 0, "root", "root", now);
90
91           if (!strcasecmp(kind, "kerberos4"))
92             dump_krb_acl(out, "LIST", lid, 4);
93           else if (!strcasecmp(kind, "kerberos5"))
94             dump_krb_acl(out, "LIST", lid, 5);
95           else if (!strcasecmp(kind, "access"))
96             dump_access_file(out, lid);
97           else if (!strcasecmp(kind, "discuss"))
98             dump_discuss_acl(out, lid);
99           else if (!strcasecmp(kind, "passwd"))
100             dump_passwd_file(out, lid);
101           else if (!strcasecmp(kind, "group"))
102             dump_group_file(out, lid);
103
104           tarfile_end(tf);
105         }
106
107       tarfile_close(tf);
108     }
109
110   EXEC SQL COMMIT RELEASE;
111
112   exit(MR_SUCCESS);
113 }
114
115 void dump_access_file(FILE *out, int lid)
116 {
117   struct save_queue *sq = get_acl("LIST", lid, merge_access_bits);
118   struct imember *m;
119
120   while (sq_remove_data(sq, &m))
121     {
122       if (m->type == 'U' ||
123           (m->type == 'S' && m->name[0] == '*'))
124         {
125           if (*(m->tag))
126             fprintf(out, "%-10s %s\n", m->name, m->tag);
127           else
128             fprintf(out, "%-10s rl\n", m->name);
129         }
130       freeimember(m);
131     }
132   sq_destroy(sq);
133 }
134
135 char *merge_access_bits(char *t1, char *t2)
136 {
137   char *m = NULL, *ans;
138   int r = 1, l = 1;
139
140   /* Clear bits that aren't granted by both tags. */
141   if ((*t1 && t1[0] != 'r' && t1[1] != 'r') ||
142       (*t2 && t2[0] != 'r' && t2[1] != 'r'))
143     r = 0;
144   if ((*t1 && t1[0] != 'l' && t1[1] != 'l') ||
145       (*t2 && t2[0] != 'l' && t2[1] != 'l'))
146     l = 0;
147
148   if (!r || !l)
149     {
150       /* Skip to message part of tag 1 */
151       m = t1;
152       while (*m && !isspace(*m))
153         m++;
154       while (isspace(*m))
155         m++;
156
157       /* If nothing there, skip to message part of tag 2 */
158       if (!*m)
159         {
160           m = t2;
161           while (*m && !isspace(*m))
162             m++;
163           while (isspace(*m))
164             m++;
165         }
166
167       ans = malloc(4 + strlen(m));
168       sprintf(ans, "%c  %s", r ? 'r' : l ? 'l' : '-', m);
169     }
170   else
171     {
172       ans = malloc(3);
173       strcpy(ans, "rl");
174     }
175   return ans;
176 }
177
178 void dump_discuss_acl(FILE *out, int lid)
179 {
180   struct save_queue *sq = get_acl("LIST", lid, merge_discuss_acls);
181   struct imember *m;
182   char name[STRINGS_STRING_SIZE], *bits;
183   int num;
184
185   num = 0;
186   while (sq_get_data(sq, &m))
187     num++;
188
189   fprintf(out, "%d\n", num);
190   while (sq_remove_data(sq, &m))
191     {
192       if (m->type != 'S')
193         {
194           canon_krb(m, 4, name, sizeof(name));
195           bits = merge_discuss_acls(m->tag, "");
196           fprintf(out, "%s    %s\n", bits, name);
197           free(bits);
198         }
199       freeimember(m);
200     }
201   sq_destroy(sq);
202 }
203
204 char *merge_discuss_acls(char *one, char *two)
205 {
206   char bits[8];
207
208   sprintf(bits, "%c%c%c%c%c%c%c",
209           strchr(one, 'a') || strchr(two, 'a') ? 'a' : ' ',
210           strchr(one, 'c') || strchr(two, 'c') ? 'c' : ' ',
211           strchr(one, 'd') || strchr(two, 'd') ? 'd' : ' ',
212           strchr(one, 'o') || strchr(two, 'o') ? 'o' : ' ',
213           strchr(one, 'r') || strchr(two, 'r') ? 'r' : ' ',
214           strchr(one, 's') || strchr(two, 's') ? 's' : ' ',
215           strchr(one, 'w') || strchr(two, 'w') ? 'w' : ' ');
216   return strdup(bits);
217 }
218
219 void dump_passwd_file(FILE *out, int lid)
220 {
221   struct save_queue *sq = get_acl("LIST", lid, NULL);
222   struct imember *m;
223   EXEC SQL BEGIN DECLARE SECTION;
224   char shell[USERS_SHELL_SIZE], fullname[USERS_FULLNAME_SIZE];
225   char nickname[USERS_NICKNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE];
226   char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE];
227   int uid;
228   char *name;
229   EXEC SQL END DECLARE SECTION;
230
231   while (sq_remove_data(sq, &m))
232     {
233       switch (m->type)
234         {
235         case 'U':
236           name = m->name;
237
238           EXEC SQL SELECT unix_uid, shell, fullname, nickname,
239             office_addr, office_phone, home_phone
240             INTO :uid, :shell, :fullname, :nickname, :oa, :op, :hp
241             FROM users
242             WHERE login = :name AND status != 3;
243           if (sqlca.sqlcode)
244             continue;
245
246           strtrim(shell);
247           strtrim(fullname);
248           strtrim(nickname);
249           strtrim(op);
250           strtrim(oa);
251           strtrim(hp);
252
253           fprintf(out, "%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\n",
254                   name, uid, fullname, nickname, oa, op, hp, name, shell);
255           break;
256         }
257       freeimember(m);
258     }
259   sq_destroy(sq);
260 }
261
262 /* This one is a bit weird since we actually look at top-level
263  * lists rather then flattening them.
264  */
265 void dump_group_file(FILE *out, int id)
266 {
267   EXEC SQL BEGIN DECLARE SECTION;
268   int lid = id, mid, gid, grouplist;
269   char mtype[IMEMBERS_MEMBER_TYPE_SIZE], name[LIST_NAME_SIZE];
270   EXEC SQL END DECLARE SECTION;
271   struct save_queue *sq;
272   struct imember *m;
273   char *maybecomma, *s;
274
275   EXEC SQL DECLARE csr_grp CURSOR FOR
276     SELECT member_type, member_id FROM imembers
277     WHERE list_id = :lid AND direct = 1;
278   EXEC SQL OPEN csr_grp;
279   while (1)
280     {
281       EXEC SQL FETCH csr_grp INTO :mtype, :mid;
282       if (sqlca.sqlcode)
283         break;
284
285       switch (*mtype)
286         {
287         case 'L':
288           EXEC SQL SELECT name, gid, grouplist
289             INTO :name, :gid, :grouplist
290             FROM list
291             WHERE list_id = :mid;
292           if (sqlca.sqlcode || !grouplist)
293             break;
294
295           strtrim(name);
296
297           fprintf(out, "%s:*:%d:", name, gid);
298           sq = get_acl("LIST", mid, NULL);
299           maybecomma = "";
300           while (sq_remove_data(sq, &m))
301             {
302               if (m->type == 'U')
303                 {
304                   fprintf(out, "%s%s", maybecomma, m->name);
305                   maybecomma = ",";
306                 }
307               freeimember(m);
308             }
309           fprintf(out, "\n");
310           sq_destroy(sq);
311           break;
312         }
313     }
314   EXEC SQL CLOSE csr_grp;
315 }
316
317 void sqlerr(void)
318 {
319   db_error(sqlca.sqlcode);
320   exit(MR_DBMS_ERR);
321 }
This page took 0.154345 seconds and 5 git commands to generate.