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