]> andersk Git - moira.git/blob - gen/genacl.pc
Build without krb4 if it's unavailable.
[moira.git] / gen / genacl.pc
1 /* $Id$
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
26 EXEC SQL INCLUDE sqlca;
27
28 RCSID("$Header$");
29
30 static char *defaultrealm = NULL;
31
32 static struct hash *users, *strings;
33
34 static void save_imember(struct save_queue *sq, char *type, int id, char *tag);
35 static struct imember *imember(char type, char *name, char *tag);
36 static struct save_queue *merge_imembers(struct save_queue *sq,
37                                          char *(merge_func)(char *, char *));
38
39 void 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
60 void 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
84 void 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       /* We assume we have a krb4-style namespace.  If we want a krb5 acl, we need to
97        * krb5_425_conv_principal() on it. For krb4, do nothing special.
98        */ 
99       at = strchr(m->name, '@');
100       if (!at)
101         at = strchr(m->name, '\0');
102       snprintf(kbuf, len, "%s", m->name);
103
104       if (!*at)
105         {
106           int plen = strlen(kbuf);
107           snprintf(kbuf + plen, len - plen, "@%s", defaultrealm);
108         }
109
110       if (vers == 5)
111         {
112           char name[ANAME_SZ] = "\0", inst[INST_SZ] = "\0", realm[REALM_SZ] = "\0";
113           char *kuser = NULL;
114           krb5_context context = NULL;
115           krb5_principal client = NULL;
116           int status = 0;
117
118           if (mr_kname_parse(name, inst, realm, kbuf) != 0)
119             goto out;
120
121           status = krb5_init_context(&context);
122           if (status)
123             goto out;
124
125           status = krb5_425_conv_principal(context, name, inst, realm, &client);
126           if (status)
127             goto out;
128
129           status = krb5_unparse_name(context, client, &kuser);
130           if (status)
131             goto out;
132
133           strncpy(buf, kuser, MAX_K_NAME_SZ);
134           buf[MAX_K_NAME_SZ - 1] = '\0';
135
136         out:
137           if (kuser)
138             krb5_free_unparsed_name(context, kuser);
139           if (client)
140             krb5_free_principal(context, client);
141           if (context)
142             krb5_free_context(context);
143         }
144       else
145         {
146           /* v4 output, and we should already have added a realm. */
147           snprintf(buf, len, "%s", kbuf);
148         }
149       break;
150     }
151 }
152
153 void dump_user_list(FILE *out, char *type, int id)
154 {
155   struct save_queue *sq;
156   struct imember *m;
157
158   sq = get_acl(type, id, NULL);
159   while (sq_remove_data(sq, &m))
160     {
161       if (m->type == 'U' || (m->type == 'S' && !strchr(m->name, '@')))
162         fprintf(out, "%s\n", m->name);
163       freeimember(m);
164     }
165   sq_destroy(sq);
166 }
167
168 struct save_queue *get_acl(char *type, int id,
169                            char *(merge_func)(char *, char *))
170 {
171   struct save_queue *sq;
172
173   sq = sq_create();
174   save_imember(sq, type, id, NULL);
175   return merge_imembers(sq, merge_func);
176 }
177
178 static void save_imember(struct save_queue *sq, char *type, int id, char *tag)
179 {
180   EXEC SQL BEGIN DECLARE SECTION;
181   int lid = id, mid, mid2, tagid, status;
182   char mtype[IMEMBERS_MEMBER_TYPE_SIZE];
183   EXEC SQL END DECLARE SECTION;
184   char *mtag;
185
186   switch (*type)
187     {
188     case 'U':
189       EXEC SQL SELECT status INTO :status FROM users WHERE users_id = :id;
190       if (status != 3)
191         sq_save_data(sq, imember('U', user_lookup(id), tag));
192       break;
193
194     case 'K':
195     case 'S':
196       sq_save_data(sq, imember(*type, string_lookup(id), tag));
197       break;
198
199     case 'L':
200       EXEC SQL DECLARE csr_acl_mem CURSOR FOR
201         SELECT member_type, member_id, tag FROM imembers
202         WHERE list_id = :lid AND direct = 1;
203       EXEC SQL OPEN csr_acl_mem;
204       while (1)
205         {
206           EXEC SQL FETCH csr_acl_mem INTO :mtype, :mid, :tagid;
207           if (sqlca.sqlcode)
208             break;
209
210           if (tag)
211             mtag = tag;
212           else
213             mtag = string_lookup(tagid);
214           if (mtype[0] == 'L')
215             {
216               EXEC SQL DECLARE csr_list CURSOR FOR
217                 SELECT member_type, member_id FROM imembers
218                 WHERE list_id = :mid AND member_type != 'LIST';
219               EXEC SQL OPEN csr_list;
220               while (1)
221                 {
222                   EXEC SQL FETCH csr_list INTO :mtype, :mid;
223                   if (sqlca.sqlcode)
224                     break;
225
226                   save_imember(sq, mtype, mid, mtag);
227                 }
228               EXEC SQL CLOSE csr_list;
229             }
230           else
231             save_imember(sq, mtype, mid, mtag);
232         }
233     }
234 }
235
236 static struct save_queue *merge_imembers(struct save_queue *sq,
237                                          char *(merge_func)(char *, char *))
238 {
239   int n;
240   struct imember *m1, *m2;
241   struct save_queue *out;
242   char *t1;
243
244   out = sq_create();
245   while (sq_remove_data(sq, &m1))
246     {
247       while (sq_get_data(sq, &m2))
248         {
249           if (m1->type == m2->type && !strcmp(m1->name, m2->name))
250             {
251               sq_remove_last_data(sq);
252               if (merge_func)
253                 {
254                   t1 = m1->tag;
255                   m1->tag = merge_func(m1->tag, m2->tag);
256                   free(t1);
257                 }
258               freeimember(m2);
259             }
260         }
261       sq_save_data(out, m1);
262     }
263   sq_destroy(sq);
264   return out;
265 }  
266
267 static struct imember *imember(char type, char *name, char *tag)
268 {
269   struct imember *m;
270   m = malloc(sizeof(struct imember));
271   m->type = type;
272   m->name = name;
273   m->tag = strdup(tag ? tag : "");
274   return m;
275 }
276
277 void freeimember(struct imember *m)
278 {
279   free(m->tag);
280   free(m);
281 }
282
283 char *user_lookup(int users_id)
284 {
285   char *u;
286
287   u = hash_lookup(users, users_id);
288   if (u)
289     return u;
290   else
291     {
292       EXEC SQL BEGIN DECLARE SECTION;
293       char login[USERS_LOGIN_SIZE];
294       EXEC SQL END DECLARE SECTION;
295
296       EXEC SQL SELECT login INTO :login FROM users
297         WHERE users_id = :users_id;
298       if (sqlca.sqlcode)
299         return NULL;
300
301       u = strdup(strtrim(login));
302       hash_store(users, users_id, u);
303       return u;
304     }
305 }
306
307 char *string_lookup(int string_id)
308 {
309   char *s;
310
311   s = hash_lookup(strings, string_id);
312   if (s)
313     return s;
314   else
315     {
316       EXEC SQL BEGIN DECLARE SECTION;
317       char string[STRINGS_STRING_SIZE];
318       EXEC SQL END DECLARE SECTION;
319
320       EXEC SQL SELECT string INTO :string FROM strings
321         WHERE string_id = :string_id;
322       if (sqlca.sqlcode)
323         return NULL;
324
325       s = strdup(strtrim(string));
326       hash_store(strings, string_id, s);
327       return s;
328     }
329 }
This page took 0.082562 seconds and 5 git commands to generate.