Home | History | Annotate | Download | only in srv
      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 			       &regexp)) != 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