xref: /freebsd/crypto/krb5/src/lib/kadm5/srv/svr_iters.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4  *
5  * $Header$
6  */
7 
8 #include "autoconf.h"
9 #if defined(HAVE_COMPILE) && defined(HAVE_STEP)
10 #define SOLARIS_REGEXPS
11 #elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
12 #define POSIX_REGEXPS
13 #elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
14 #define BSD_REGEXPS
15 #else
16 #error I cannot find any regexp functions
17 #endif
18 
19 #include        <sys/types.h>
20 #include        <string.h>
21 #include        <kadm5/admin.h>
22 #ifdef SOLARIS_REGEXPS
23 #include        <regexpr.h>
24 #endif
25 #ifdef POSIX_REGEXPS
26 #include        <regex.h>
27 #endif
28 #include <stdlib.h>
29 
30 #include        "server_internal.h"
31 
32 struct iter_data {
33     krb5_context context;
34     char **names;
35     int n_names, sz_names;
36     unsigned int malloc_failed;
37     char *exp;
38 #ifdef SOLARIS_REGEXPS
39     char *expbuf;
40 #endif
41 #ifdef POSIX_REGEXPS
42     regex_t preg;
43 #endif
44 };
45 
46 /* XXX Duplicated in kdb5_util!  */
47 /*
48  * Function: glob_to_regexp
49  *
50  * Arguments:
51  *
52  *      glob    (r) the shell-style glob (?*[]) to convert
53  *      realm   (r) the default realm to append, or NULL
54  *      regexp  (w) the ed-style regexp created from glob
55  *
56  * Effects:
57  *
58  * regexp is filled in with allocated memory contained a regular
59  * expression to be used with re_comp/compile that matches what the
60  * shell-style glob would match.  If glob does not contain an "@"
61  * character and realm is not NULL, "@*" is appended to the regexp.
62  *
63  * Conversion algorithm:
64  *
65  *      quoted characters are copied quoted
66  *      ? is converted to .
67  *      * is converted to .*
68  *      active characters are quoted: ^, $, .
69  *      [ and ] are active but supported and have the same meaning, so
70  *              they are copied
71  *      other characters are copied
72  *      regexp is anchored with ^ and $
73  */
glob_to_regexp(char * glob,char * realm,char ** regexp)74 static kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
75 {
76     int append_realm;
77     char *p;
78 
79     /* validate the glob */
80     if (glob[strlen(glob)-1] == '\\')
81         return EINVAL;
82 
83     /* A character of glob can turn into two in regexp, plus ^ and $ */
84     /* and trailing null.  If glob has no @, also allocate space for */
85     /* the realm. */
86     append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
87     p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0));
88     if (p == NULL)
89         return ENOMEM;
90     *regexp = p;
91 
92     *p++ = '^';
93     while (*glob) {
94         switch (*glob) {
95         case '?':
96             *p++ = '.';
97             break;
98         case '*':
99             *p++ = '.';
100             *p++ = '*';
101             break;
102         case '.':
103         case '^':
104         case '$':
105             *p++ = '\\';
106             *p++ = *glob;
107             break;
108         case '\\':
109             *p++ = '\\';
110             *p++ = *++glob;
111             break;
112         default:
113             *p++ = *glob;
114             break;
115         }
116         glob++;
117     }
118 
119     if (append_realm) {
120         *p++ = '@';
121         *p++ = '.';
122         *p++ = '*';
123     }
124 
125     *p++ = '$';
126     *p++ = '\0';
127     return KADM5_OK;
128 }
129 
get_either_iter(struct iter_data * data,char * name)130 static void get_either_iter(struct iter_data *data, char *name)
131 {
132     int match;
133 #ifdef SOLARIS_REGEXPS
134     match = (step(name, data->expbuf) != 0);
135 #endif
136 #ifdef POSIX_REGEXPS
137     match = (regexec(&data->preg, name, 0, NULL, 0) == 0);
138 #endif
139 #ifdef BSD_REGEXPS
140     match = (re_exec(name) != 0);
141 #endif
142     if (match) {
143         if (data->n_names == data->sz_names) {
144             int new_sz = data->sz_names * 2;
145             char **new_names = realloc(data->names,
146                                        new_sz * sizeof(char *));
147             if (new_names) {
148                 data->names = new_names;
149                 data->sz_names = new_sz;
150             } else {
151                 data->malloc_failed = 1;
152                 free(name);
153                 return;
154             }
155         }
156         data->names[data->n_names++] = name;
157     } else
158         free(name);
159 }
160 
get_pols_iter(void * data,osa_policy_ent_t entry)161 static void get_pols_iter(void *data, osa_policy_ent_t entry)
162 {
163     char *name;
164 
165     if ((name = strdup(entry->name)) == NULL)
166         return;
167     get_either_iter(data, name);
168 }
169 
get_princs_iter(void * data,krb5_principal princ)170 static void get_princs_iter(void *data, krb5_principal princ)
171 {
172     struct iter_data *id = (struct iter_data *) data;
173     char *name;
174 
175     if (krb5_unparse_name(id->context, princ, &name) != 0)
176         return;
177     get_either_iter(data, name);
178 }
179 
kadm5_get_either(int princ,void * server_handle,char * exp,char *** princs,int * count)180 static kadm5_ret_t kadm5_get_either(int princ,
181                                     void *server_handle,
182                                     char *exp,
183                                     char ***princs,
184                                     int *count)
185 {
186     struct iter_data data;
187 #ifdef BSD_REGEXPS
188     char *msg;
189 #endif
190     char *regexp = NULL;
191     int i, ret;
192     kadm5_server_handle_t handle = server_handle;
193 
194     *princs = NULL;
195     *count = 0;
196     if (exp == NULL)
197         exp = "*";
198 
199     CHECK_HANDLE(server_handle);
200 
201     if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL,
202                               &regexp)) != KADM5_OK)
203         return ret;
204 
205     if (
206 #ifdef SOLARIS_REGEXPS
207         ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
208 #endif
209 #ifdef POSIX_REGEXPS
210         ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
211 #endif
212 #ifdef BSD_REGEXPS
213         ((msg = (char *) re_comp(regexp)) != NULL)
214 #endif
215     )
216     {
217         /* XXX syslog msg or regerr(regerrno) */
218         free(regexp);
219         return EINVAL;
220     }
221 
222     data.n_names = 0;
223     data.sz_names = 10;
224     data.malloc_failed = 0;
225     data.names = malloc(sizeof(char *) * data.sz_names);
226     if (data.names == NULL) {
227         free(regexp);
228         return ENOMEM;
229     }
230 
231     if (princ) {
232         data.context = handle->context;
233         ret = kdb_iter_entry(handle, exp, get_princs_iter, (void *) &data);
234     } else {
235         ret = krb5_db_iter_policy(handle->context, exp, get_pols_iter, (void *)&data);
236     }
237 
238     free(regexp);
239 #ifdef POSIX_REGEXPS
240     regfree(&data.preg);
241 #endif
242     if ( !ret && data.malloc_failed)
243         ret = ENOMEM;
244     if ( ret ) {
245         for (i = 0; i < data.n_names; i++)
246             free(data.names[i]);
247         free(data.names);
248         return ret;
249     }
250 
251     *princs = data.names;
252     *count = data.n_names;
253     return KADM5_OK;
254 }
255 
kadm5_get_principals(void * server_handle,char * exp,char *** princs,int * count)256 kadm5_ret_t kadm5_get_principals(void *server_handle,
257                                  char *exp,
258                                  char ***princs,
259                                  int *count)
260 {
261     return kadm5_get_either(1, server_handle, exp, princs, count);
262 }
263 
kadm5_get_policies(void * server_handle,char * exp,char *** pols,int * count)264 kadm5_ret_t kadm5_get_policies(void *server_handle,
265                                char *exp,
266                                char ***pols,
267                                int *count)
268 {
269     return kadm5_get_either(0, server_handle, exp, pols, count);
270 }
271