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