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