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
10 #include <sys/types.h>
11 #include <string.h>
12 #include <kadm5/admin.h>
13 #include "k5-regex.h"
14 #include <stdlib.h>
15
16 #include "server_internal.h"
17
18 struct iter_data {
19 krb5_context context;
20 char **names;
21 int n_names, sz_names;
22 unsigned int malloc_failed;
23 char *exp;
24 regex_t preg;
25 };
26
27 /* XXX Duplicated in kdb5_util! */
28 /*
29 * Function: glob_to_regexp
30 *
31 * Arguments:
32 *
33 * glob (r) the shell-style glob (?*[]) to convert
34 * realm (r) the default realm to append, or NULL
35 * regexp (w) the ed-style regexp created from glob
36 *
37 * Effects:
38 *
39 * regexp is filled in with allocated memory contained a regular
40 * expression that matches what the shell-style glob would match.
41 * If glob does not contain an "@" character and realm is not
42 * NULL, "@*" is appended to the regexp.
43 *
44 * Conversion algorithm:
45 *
46 * quoted characters are copied quoted
47 * ? is converted to .
48 * * is converted to .*
49 * active characters are quoted: ^, $, .
50 * [ and ] are active but supported and have the same meaning, so
51 * they are copied
52 * other characters are copied
53 * regexp is anchored with ^ and $
54 */
glob_to_regexp(char * glob,char * realm,char ** regexp)55 static kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
56 {
57 int append_realm;
58 char *p;
59
60 /* validate the glob */
61 if (glob[strlen(glob)-1] == '\\')
62 return EINVAL;
63
64 /* A character of glob can turn into two in regexp, plus ^ and $ */
65 /* and trailing null. If glob has no @, also allocate space for */
66 /* the realm. */
67 append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
68 p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0));
69 if (p == NULL)
70 return ENOMEM;
71 *regexp = p;
72
73 *p++ = '^';
74 while (*glob) {
75 switch (*glob) {
76 case '?':
77 *p++ = '.';
78 break;
79 case '*':
80 *p++ = '.';
81 *p++ = '*';
82 break;
83 case '.':
84 case '^':
85 case '$':
86 *p++ = '\\';
87 *p++ = *glob;
88 break;
89 case '\\':
90 *p++ = '\\';
91 *p++ = *++glob;
92 break;
93 default:
94 *p++ = *glob;
95 break;
96 }
97 glob++;
98 }
99
100 if (append_realm) {
101 *p++ = '@';
102 *p++ = '.';
103 *p++ = '*';
104 }
105
106 *p++ = '$';
107 *p++ = '\0';
108 return KADM5_OK;
109 }
110
get_either_iter(struct iter_data * data,char * name)111 static void get_either_iter(struct iter_data *data, char *name)
112 {
113 int match;
114 match = (regexec(&data->preg, name, 0, NULL, 0) == 0);
115 if (match) {
116 if (data->n_names == data->sz_names) {
117 int new_sz = data->sz_names * 2;
118 char **new_names = realloc(data->names,
119 new_sz * sizeof(char *));
120 if (new_names) {
121 data->names = new_names;
122 data->sz_names = new_sz;
123 } else {
124 data->malloc_failed = 1;
125 free(name);
126 return;
127 }
128 }
129 data->names[data->n_names++] = name;
130 } else
131 free(name);
132 }
133
get_pols_iter(void * data,osa_policy_ent_t entry)134 static void get_pols_iter(void *data, osa_policy_ent_t entry)
135 {
136 char *name;
137
138 if ((name = strdup(entry->name)) == NULL)
139 return;
140 get_either_iter(data, name);
141 }
142
get_princs_iter(void * data,krb5_principal princ)143 static void get_princs_iter(void *data, krb5_principal princ)
144 {
145 struct iter_data *id = (struct iter_data *) data;
146 char *name;
147
148 if (krb5_unparse_name(id->context, princ, &name) != 0)
149 return;
150 get_either_iter(data, name);
151 }
152
kadm5_get_either(int princ,void * server_handle,char * exp,char *** princs,int * count)153 static kadm5_ret_t kadm5_get_either(int princ,
154 void *server_handle,
155 char *exp,
156 char ***princs,
157 int *count)
158 {
159 struct iter_data data;
160 char *regexp = NULL;
161 int i, ret;
162 kadm5_server_handle_t handle = server_handle;
163
164 *princs = NULL;
165 *count = 0;
166 if (exp == NULL)
167 exp = "*";
168
169 CHECK_HANDLE(server_handle);
170
171 if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL,
172 ®exp)) != KADM5_OK)
173 return ret;
174
175 if (regcomp(&data.preg, regexp, REG_NOSUB) != 0) {
176 /* XXX syslog msg or regerr(regerrno) */
177 free(regexp);
178 return EINVAL;
179 }
180
181 data.n_names = 0;
182 data.sz_names = 10;
183 data.malloc_failed = 0;
184 data.names = malloc(sizeof(char *) * data.sz_names);
185 if (data.names == NULL) {
186 free(regexp);
187 return ENOMEM;
188 }
189
190 if (princ) {
191 data.context = handle->context;
192 ret = kdb_iter_entry(handle, exp, get_princs_iter, (void *) &data);
193 } else {
194 ret = krb5_db_iter_policy(handle->context, exp, get_pols_iter, (void *)&data);
195 }
196
197 free(regexp);
198 regfree(&data.preg);
199 if ( !ret && data.malloc_failed)
200 ret = ENOMEM;
201 if ( ret ) {
202 for (i = 0; i < data.n_names; i++)
203 free(data.names[i]);
204 free(data.names);
205 return ret;
206 }
207
208 *princs = data.names;
209 *count = data.n_names;
210 return KADM5_OK;
211 }
212
kadm5_get_principals(void * server_handle,char * exp,char *** princs,int * count)213 kadm5_ret_t kadm5_get_principals(void *server_handle,
214 char *exp,
215 char ***princs,
216 int *count)
217 {
218 return kadm5_get_either(1, server_handle, exp, princs, count);
219 }
220
kadm5_get_policies(void * server_handle,char * exp,char *** pols,int * count)221 kadm5_ret_t kadm5_get_policies(void *server_handle,
222 char *exp,
223 char ***pols,
224 int *count)
225 {
226 return kadm5_get_either(0, server_handle, exp, pols, count);
227 }
228