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

Revision 25817, 6.6 KB checked in by jdreed, 11 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
Line 
1/* $Id: genacl.pc 4092 2013-01-18 15:36:33Z zacheiss $
2 *
3 * Utility functions for outputting ACLs
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 <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#ifdef HAVE_KRB4
20#include <krb.h>
21#else
22#include <mr_krb.h>
23#endif
24#include <krb5.h>
25
26EXEC SQL INCLUDE sqlca;
27
28RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/gen/genacl.pc $ $Id: genacl.pc 4092 2013-01-18 15:36:33Z zacheiss $");
29
30static char *defaultrealm = NULL;
31
32static struct hash *users, *strings;
33
34static void save_imember(struct save_queue *sq, char *type, int id, char *tag);
35static struct imember *imember(char type, char *name, char *tag);
36static struct save_queue *merge_imembers(struct save_queue *sq,
37                                         char *(merge_func)(char *, char *));
38
39void init_acls(void)
40{
41  krb5_context context = NULL;
42  int code;
43
44  users = create_hash(2000);
45  strings = create_hash(2000);
46
47  code = krb5_init_context(&context);
48  if (code)
49    goto out;
50
51  code = krb5_get_default_realm(context, &defaultrealm);
52  if (code)
53    goto out;
54
55 out:
56  if (context)
57    krb5_free_context(context);
58}
59
60void dump_krb_acl(FILE *out, char *type, int id, int vers)
61{
62  struct save_queue *sq;
63  struct imember *m;
64  char kbuf[MAX_K_NAME_SZ];
65
66  sq = get_acl(type, id, NULL);
67  while (sq_remove_data(sq, &m))
68    {
69      if (m->name == NULL)
70        {
71          fprintf(stderr, "Found string_id with no associated string.  Exiting.\n");
72          exit(MR_DBMS_ERR);
73        }
74      if (m->type != 'S')
75        {
76          canon_krb(m, vers, kbuf, sizeof(kbuf));
77          fprintf(out, "%s\n", kbuf);
78        }
79      freeimember(m);
80    }
81  sq_destroy(sq);
82}
83
84void canon_krb(struct imember *m, int vers, char *buf, int len)
85{
86  char *at;
87  char kbuf[MAX_K_NAME_SZ];
88
89  switch (m->type)
90    {
91    case 'U':
92      snprintf(buf, len, "%s@%s", m->name, defaultrealm);
93      break;
94
95    case 'K':
96
97      at = strchr(m->name, '@');
98      if (!at)
99        at = strchr(m->name, '\0');
100      snprintf(kbuf, len, "%s", m->name);
101
102      if (!*at)
103        {
104          int plen = strlen(kbuf);
105          snprintf(kbuf + plen, len - plen, "@%s", defaultrealm);
106        }
107
108      /* Assume a v5 namespace, convert if krb4 requested. */
109      if (vers == 4)
110        {
111          krb5_context context = NULL;
112          krb5_principal client = NULL;
113          int status = 0;
114          char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
115
116          status = krb5_init_context(&context);
117          if (status)
118            goto out;
119
120          status = krb5_parse_name(context, kbuf, &client);
121          if (status)
122            goto out;
123
124          status = krb5_524_conv_principal(context, client, name, inst, realm);
125          if (status)
126            goto out;
127
128          snprintf(buf, len, "%s", mr_kname_unparse(name, inst, realm));
129
130        out:
131          if (client)
132            krb5_free_principal(context, client);
133          if (context)
134            krb5_free_context(context);
135        }
136      else
137        snprintf(buf, len, "%s", kbuf);
138      break;
139    }
140}
141
142void dump_user_list(FILE *out, char *type, int id)
143{
144  struct save_queue *sq;
145  struct imember *m;
146
147  sq = get_acl(type, id, NULL);
148  while (sq_remove_data(sq, &m))
149    {
150      if (m->type == 'U' || (m->type == 'S' && !strchr(m->name, '@')))
151        fprintf(out, "%s\n", m->name);
152      freeimember(m);
153    }
154  sq_destroy(sq);
155}
156
157struct save_queue *get_acl(char *type, int id,
158                           char *(merge_func)(char *, char *))
159{
160  struct save_queue *sq;
161
162  sq = sq_create();
163  save_imember(sq, type, id, NULL);
164  return merge_imembers(sq, merge_func);
165}
166
167static void save_imember(struct save_queue *sq, char *type, int id, char *tag)
168{
169  EXEC SQL BEGIN DECLARE SECTION;
170  int lid = id, mid, mid2, tagid, status;
171  char mtype[IMEMBERS_MEMBER_TYPE_SIZE];
172  EXEC SQL END DECLARE SECTION;
173  char *mtag;
174
175  switch (*type)
176    {
177    case 'U':
178      EXEC SQL SELECT status INTO :status FROM users WHERE users_id = :id;
179      if (status != 3)
180        sq_save_data(sq, imember('U', user_lookup(id), tag));
181      break;
182
183    case 'K':
184    case 'S':
185      sq_save_data(sq, imember(*type, string_lookup(id), tag));
186      break;
187
188    case 'L':
189      EXEC SQL DECLARE csr_acl_mem CURSOR FOR
190        SELECT member_type, member_id, tag FROM imembers
191        WHERE list_id = :lid AND direct = 1;
192      EXEC SQL OPEN csr_acl_mem;
193      while (1)
194        {
195          EXEC SQL FETCH csr_acl_mem INTO :mtype, :mid, :tagid;
196          if (sqlca.sqlcode)
197            break;
198
199          if (tag)
200            mtag = tag;
201          else
202            mtag = string_lookup(tagid);
203          if (mtype[0] == 'L')
204            {
205              EXEC SQL DECLARE csr_list CURSOR FOR
206                SELECT member_type, member_id FROM imembers
207                WHERE list_id = :mid AND member_type != 'LIST';
208              EXEC SQL OPEN csr_list;
209              while (1)
210                {
211                  EXEC SQL FETCH csr_list INTO :mtype, :mid;
212                  if (sqlca.sqlcode)
213                    break;
214
215                  save_imember(sq, mtype, mid, mtag);
216                }
217              EXEC SQL CLOSE csr_list;
218            }
219          else
220            save_imember(sq, mtype, mid, mtag);
221        }
222    }
223}
224
225static struct save_queue *merge_imembers(struct save_queue *sq,
226                                         char *(merge_func)(char *, char *))
227{
228  int n;
229  struct imember *m1, *m2;
230  struct save_queue *out;
231  char *t1;
232
233  out = sq_create();
234  while (sq_remove_data(sq, &m1))
235    {
236      while (sq_get_data(sq, &m2))
237        {
238          if (m1->type == m2->type && !strcmp(m1->name, m2->name))
239            {
240              sq_remove_last_data(sq);
241              if (merge_func)
242                {
243                  t1 = m1->tag;
244                  m1->tag = merge_func(m1->tag, m2->tag);
245                  free(t1);
246                }
247              freeimember(m2);
248            }
249        }
250      sq_save_data(out, m1);
251    }
252  sq_destroy(sq);
253  return out;
254
255
256static struct imember *imember(char type, char *name, char *tag)
257{
258  struct imember *m;
259  m = malloc(sizeof(struct imember));
260  m->type = type;
261  m->name = name;
262  m->tag = strdup(tag ? tag : "");
263  return m;
264}
265
266void freeimember(struct imember *m)
267{
268  free(m->tag);
269  free(m);
270}
271
272char *user_lookup(int users_id)
273{
274  char *u;
275
276  u = hash_lookup(users, users_id);
277  if (u)
278    return u;
279  else
280    {
281      EXEC SQL BEGIN DECLARE SECTION;
282      char login[USERS_LOGIN_SIZE];
283      EXEC SQL END DECLARE SECTION;
284
285      EXEC SQL SELECT login INTO :login FROM users
286        WHERE users_id = :users_id;
287      if (sqlca.sqlcode)
288        return NULL;
289
290      u = strdup(strtrim(login));
291      hash_store(users, users_id, u);
292      return u;
293    }
294}
295
296char *string_lookup(int string_id)
297{
298  char *s;
299
300  s = hash_lookup(strings, string_id);
301  if (s)
302    return s;
303  else
304    {
305      EXEC SQL BEGIN DECLARE SECTION;
306      char string[STRINGS_STRING_SIZE];
307      EXEC SQL END DECLARE SECTION;
308
309      EXEC SQL SELECT string INTO :string FROM strings
310        WHERE string_id = :string_id;
311      if (sqlca.sqlcode)
312        return NULL;
313
314      s = strdup(strtrim(string));
315      hash_store(strings, string_id, s);
316      return s;
317    }
318}
Note: See TracBrowser for help on using the repository browser.