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 ®exp)) != 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