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