xref: /illumos-gate/usr/src/lib/krb5/kadm5/srv/svr_iters.c (revision e00bdde3c6d406f40f53f3025defadc22f7ec31a)
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  */
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 
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 
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 
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 
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 			       &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 
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 
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