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 ®exp)) != 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