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__)
27static 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
54struct 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 */
95static 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
150static 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
181static 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
190static 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
200static 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			       &regexp)) != 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
275kadm5_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
283kadm5_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