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