source: trunk/third/moira/gen/acl.pc @ 25817

Revision 25817, 9.1 KB checked in by jdreed, 12 years ago (diff)
In moira: * Re-snapshot moira at r4097 to pick up Status 10 (Suspended) (Trac: #1295) * Remove our addusr.1 and namespace.1 in favor of upstreams (Trac: #918) * Build-dep on OpenSSL and pass new configure flag per moira r4091
RevLine 
[25817]1/* $Id: acl.pc 4092 2013-01-18 15:36:33Z zacheiss $
[23095]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
[23882]22#ifdef HAVE_KRB4
[23095]23#include <krb.h>
[23882]24#endif
[23095]25
26EXEC SQL INCLUDE sqlca;
27
[25817]28RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/gen/acl.pc $ $Id: acl.pc 4092 2013-01-18 15:36:33Z zacheiss $");
[23095]29
30char *whoami = "acl.gen";
31char *db = "moira/moira";
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;
44  int mid, lid, discuss_uid = -1;
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
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
[25817]109              if (!strcasecmp(kind, "kerberos5"))
[23095]110                dump_krb_acl(out, "LIST", lid, 5);
111              else if (!strcasecmp(kind, "access"))
112                dump_access_file(out, lid);
113              else if (!strcasecmp(kind, "passwd"))
114                dump_passwd_file(out, lid);
115              else if (!strcasecmp(kind, "group"))
116                dump_group_file(out, lid);
117              else if (!strcasecmp(kind, "userlist"))
118                dump_user_list(out, "LIST", lid);
119            }
120
121          tarfile_end(tf);
122        }
123
124      tarfile_close(tf);
125    }
126
127  EXEC SQL COMMIT RELEASE;
128
129  exit(MR_SUCCESS);
130}
131
132void dump_access_file(FILE *out, int lid)
133{
134  struct save_queue *sq = get_acl("LIST", lid, merge_access_bits);
135  struct imember *m;
136  char *name, *lasts = NULL;
137  int i = 0;
138
139  while (sq_remove_data(sq, &m))
140    {
141      if (m->type == 'U' ||
142          (m->type == 'S' && m->name[0] == '*'))
143        {
144          if (*(m->tag))
145            fprintf(out, "%-10s %s\n", m->name, m->tag);
146          else
147            fprintf(out, "%-10s rl\n", m->name);
148        }
149      else if (m->type == 'K')
150        {
151          name = strtok_r(m->name, "@", &lasts);
152          EXEC SQL SELECT count(login) INTO :i FROM users
153            WHERE login = :name and status != 3;
154          if (i == 1)
155            {
156              if (*(m->tag))
157                fprintf(out, "%-10s %s\n", m->name, m->tag);
158              else
159                fprintf(out, "%-10s rl\n", m->name);
160            }
161        }
162      freeimember(m);
163    }
164  sq_destroy(sq);
165}
166
167char *merge_access_bits(char *t1, char *t2)
168{
169  char *m = NULL, *ans;
170  int r = 1, l = 1;
171
172  /* Clear bits that aren't granted by both tags. */
173  if ((*t1 && t1[0] != 'r' && t1[1] != 'r') ||
174      (*t2 && t2[0] != 'r' && t2[1] != 'r'))
175    r = 0;
176  if ((*t1 && t1[0] != 'l' && t1[1] != 'l') ||
177      (*t2 && t2[0] != 'l' && t2[1] != 'l'))
178    l = 0;
179
180  if (!r || !l)
181    {
182      /* Skip to message part of tag 1 */
183      m = t1;
184      while (*m && !isspace(*m))
185        m++;
186      while (isspace(*m))
187        m++;
188
189      /* If nothing there, skip to message part of tag 2 */
190      if (!*m)
191        {
192          m = t2;
193          while (*m && !isspace(*m))
194            m++;
195          while (isspace(*m))
196            m++;
197        }
198
199      ans = malloc(4 + strlen(m));
200      sprintf(ans, "%c  %s", r ? 'r' : l ? 'l' : '-', m);
201    }
202  else
203    {
204      ans = malloc(3);
205      strcpy(ans, "rl");
206    }
207  return ans;
208}
209
210void dump_discuss_acl(FILE *out, int lid)
211{
212  struct save_queue *sq = get_acl("LIST", lid, merge_discuss_acls);
213  struct imember *m;
214  char name[STRINGS_STRING_SIZE], *bits;
215  char starbits[8] = { 0 };
216  int num;
217
218  num = 0;
219  while (sq_get_data(sq, &m))
220    {
221      if (m->type != 'S' || !strcmp(m->name, "*"))
222        num++;
223    }
224
225  fprintf(out, "%d\n", num);
226  while (sq_remove_data(sq, &m))
227    {
228      bits = merge_discuss_acls(m->tag, "");
229      if (m->type != 'S')
230        {
231          canon_krb(m, 4, name, sizeof(name));
232          fprintf(out, "%s:%s\n", bits, name);
233        }
234      else if (!strcmp(m->name, "*"))
235        strcpy(starbits, bits);
236      free(bits);
237      freeimember(m);
238    }
239  sq_destroy(sq);
240
241  /* Discuss ACLs are ordered, so "*" must come last. */
242  if (*starbits)
243    fprintf(out, "%s:*\n", starbits);
244}
245
246char *merge_discuss_acls(char *one, char *two)
247{
248  char bits[8];
249
250  sprintf(bits, "%c%c%c%c%c%c%c",
251          strchr(one, 'a') || strchr(two, 'a') ? 'a' : ' ',
252          strchr(one, 'c') || strchr(two, 'c') ? 'c' : ' ',
253          strchr(one, 'd') || strchr(two, 'd') ? 'd' : ' ',
254          strchr(one, 'o') || strchr(two, 'o') ? 'o' : ' ',
255          strchr(one, 'r') || strchr(two, 'r') ? 'r' : ' ',
256          strchr(one, 's') || strchr(two, 's') ? 's' : ' ',
257          strchr(one, 'w') || strchr(two, 'w') ? 'w' : ' ');
258  return strdup(bits);
259}
260
261void dump_passwd_file(FILE *out, int lid)
262{
263  struct save_queue *sq = get_acl("LIST", lid, NULL);
264  struct imember *m;
265  EXEC SQL BEGIN DECLARE SECTION;
266  char shell[USERS_SHELL_SIZE], fullname[USERS_FULLNAME_SIZE];
[25198]267  char oa[USERS_OFFICE_ADDR_SIZE];
[23095]268  char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE];
269  int uid, i = 0;
270  char *name, *n, *lasts = NULL;
271  EXEC SQL END DECLARE SECTION;
272
273  while (sq_remove_data(sq, &m))
274    {
275      switch (m->type)
276        {
277        case 'U':
278          name = m->name;
279
[25198]280          EXEC SQL SELECT unix_uid, shell, fullname,
[23095]281            office_addr, office_phone, home_phone
[25198]282            INTO :uid, :shell, :fullname, :oa, :op, :hp
[23095]283            FROM users
284            WHERE login = :name AND status != 3;
285          if (sqlca.sqlcode)
286            continue;
287
288          strtrim(shell);
289          strtrim(fullname);
290          strtrim(op);
291          strtrim(oa);
292          strtrim(hp);
293
[25198]294          fprintf(out, "%s:*:%d:101:%s,%s,%s,%s:/mit/%s:%s\n",
295                  name, uid, fullname, oa, op, hp, name, shell);
[23095]296          break;
297
298        case 'K':
299          name = strtok_r(m->name, "@", &lasts);
300           
301          EXEC SQL SELECT count(login) INTO :i FROM users WHERE
302            login = :name and status != 3;
303          if (i == 1)
304            {
[25198]305              EXEC SQL SELECT unix_uid, shell, fullname,
[23095]306                office_addr, office_phone, home_phone
[25198]307                INTO :uid, :shell, :fullname, :oa, :op, :hp
[23095]308                FROM users
309                WHERE login = :name AND status != 3;         
310              if (sqlca.sqlcode)
311                continue;
312             
313              strtrim(shell);
314              strtrim(fullname);
315              strtrim(op);
316              strtrim(oa);
317              strtrim(hp);
318             
[25198]319              fprintf(out, "%s:*:%d:101:%s,%s,%s,%s:/mit/%s:%s\n",
320                      name, uid, fullname, oa, op, hp, name, shell);
[23095]321            }
322          break;
323        }
324      freeimember(m);
325    }
326  sq_destroy(sq);
327}
328
329/* This one is a bit weird since we actually look at top-level
330 * lists rather then flattening them.
331 */
332void dump_group_file(FILE *out, int id)
333{
334  EXEC SQL BEGIN DECLARE SECTION;
335  int lid = id, mid, gid, grouplist, i = 0;
336  char mtype[IMEMBERS_MEMBER_TYPE_SIZE], name[LIST_NAME_SIZE];
337  EXEC SQL END DECLARE SECTION;
338  struct save_queue *sq;
339  struct imember *m;
340  char *maybecomma, *s, *n, *lasts = NULL;
341
342  EXEC SQL DECLARE csr_grp CURSOR FOR
343    SELECT member_type, member_id FROM imembers
344    WHERE list_id = :lid AND direct = 1;
345  EXEC SQL OPEN csr_grp;
346  while (1)
347    {
348      EXEC SQL FETCH csr_grp INTO :mtype, :mid;
349      if (sqlca.sqlcode)
350        break;
351
352      switch (*mtype)
353        {
354        case 'L':
355          EXEC SQL SELECT name, gid, grouplist
356            INTO :name, :gid, :grouplist
357            FROM list
358            WHERE list_id = :mid;
359          if (sqlca.sqlcode || !grouplist)
360            break;
361
362          strtrim(name);
363
364          fprintf(out, "%s:*:%d:", name, gid);
365          sq = get_acl("LIST", mid, NULL);
366          maybecomma = "";
367          while (sq_remove_data(sq, &m))
368            {
369              if (m->type == 'U')
370                {
371                  fprintf(out, "%s%s", maybecomma, m->name);
372                  maybecomma = ",";
373                }
374              else if (m->type == 'K')
375                {
376                  n = strtok_r(m->name, "@", &lasts);
377                  EXEC SQL SELECT count(login) INTO :i FROM users
378                    WHERE login = :n and status != 3;
379                  if (i == 1)
380                    {
381                      fprintf(out, "%s%s", maybecomma, n);
382                      maybecomma = ",";
383                    }
384                }
385              freeimember(m);
386            }
387          fprintf(out, "\n");
388          sq_destroy(sq);
389          break;
390        }
391    }
392  EXEC SQL CLOSE csr_grp;
393}
394
395void sqlerr(void)
396{
397  db_error(sqlca.sqlcode);
398  exit(MR_DBMS_ERR);
399}
Note: See TracBrowser for help on using the repository browser.