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