2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
2N/A *
2N/A * $Header$
2N/A */
2N/A
2N/A/*
2N/A * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
2N/A *
2N/A * Openvision retains the copyright to derivative works of
2N/A * this source code. Do *NOT* create a derivative of this
2N/A * source code before consulting with your legal department.
2N/A * Do *NOT* integrate *ANY* of this source code into another
2N/A * product before consulting with your legal department.
2N/A *
2N/A * For further information, read the top-level Openvision
2N/A * copyright which is contained in the top-level MIT Kerberos
2N/A * copyright.
2N/A *
2N/A * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
2N/A *
2N/A */
2N/A
2N/A#if !defined(lint) && !defined(__CODECENTER__)
2N/Astatic char *rcsid = "$Header$";
2N/A#endif
2N/A
2N/A#include "autoconf.h"
2N/A#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
2N/A#define SOLARIS_REGEXPS
2N/A#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
2N/A#define POSIX_REGEXPS
2N/A#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
2N/A#define BSD_REGEXPS
2N/A#else
2N/A#error I cannot find any regexp functions
2N/A#endif
2N/A
2N/A#include <sys/types.h>
2N/A#include <string.h>
2N/A#include <kadm5/admin.h>
2N/A#ifdef SOLARIS_REGEXPS
2N/A#include <regexpr.h>
2N/A#endif
2N/A#ifdef POSIX_REGEXPS
2N/A#include <regex.h>
2N/A#endif
2N/A#include <stdlib.h>
2N/A
2N/A#include "server_internal.h"
2N/A
2N/Astruct iter_data {
2N/A krb5_context context;
2N/A char **names;
2N/A int n_names, sz_names;
2N/A unsigned int malloc_failed;
2N/A char *exp;
2N/A#ifdef SOLARIS_REGEXPS
2N/A char *expbuf;
2N/A#endif
2N/A#ifdef POSIX_REGEXPS
2N/A regex_t preg;
2N/A#endif
2N/A};
2N/A
2N/A/* XXX Duplicated in kdb5_util! */
2N/A/*
2N/A * Function: glob_to_regexp
2N/A *
2N/A * Arguments:
2N/A *
2N/A * glob (r) the shell-style glob (?*[]) to convert
2N/A * realm (r) the default realm to append, or NULL
2N/A * regexp (w) the ed-style regexp created from glob
2N/A *
2N/A * Effects:
2N/A *
2N/A * regexp is filled in with allocated memory contained a regular
2N/A * expression to be used with re_comp/compile that matches what the
2N/A * shell-style glob would match. If glob does not contain an "@"
2N/A * character and realm is not NULL, "@*" is appended to the regexp.
2N/A *
2N/A * Conversion algorithm:
2N/A *
2N/A * quoted characters are copied quoted
2N/A * ? is converted to .
2N/A * * is converted to .*
2N/A * active characters are quoted: ^, $, .
2N/A * [ and ] are active but supported and have the same meaning, so
2N/A * they are copied
2N/A * other characters are copied
2N/A * regexp is anchored with ^ and $
2N/A */
2N/Astatic kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
2N/A{
2N/A int append_realm;
2N/A char *p;
2N/A
2N/A /* validate the glob */
2N/A if (glob[strlen(glob)-1] == '\\')
2N/A return EINVAL;
2N/A
2N/A /* A character of glob can turn into two in regexp, plus ^ and $ */
2N/A /* and trailing null. If glob has no @, also allocate space for */
2N/A /* the realm. */
2N/A append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
2N/A p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0));
2N/A if (p == NULL)
2N/A return ENOMEM;
2N/A *regexp = p;
2N/A
2N/A *p++ = '^';
2N/A while (*glob) {
2N/A switch (*glob) {
2N/A case '?':
2N/A *p++ = '.';
2N/A break;
2N/A case '*':
2N/A *p++ = '.';
2N/A *p++ = '*';
2N/A break;
2N/A case '.':
2N/A case '^':
2N/A case '$':
2N/A *p++ = '\\';
2N/A *p++ = *glob;
2N/A break;
2N/A case '\\':
2N/A *p++ = '\\';
2N/A *p++ = *++glob;
2N/A break;
2N/A default:
2N/A *p++ = *glob;
2N/A break;
2N/A }
2N/A glob++;
2N/A }
2N/A
2N/A if (append_realm) {
2N/A *p++ = '@';
2N/A *p++ = '.';
2N/A *p++ = '*';
2N/A }
2N/A
2N/A *p++ = '$';
2N/A *p++ = '\0';
2N/A return KADM5_OK;
2N/A}
2N/A
2N/Astatic void get_either_iter(struct iter_data *data, char *name)
2N/A{
2N/A int match;
2N/A#ifdef SOLARIS_REGEXPS
2N/A match = (step(name, data->expbuf) != 0);
2N/A#endif
2N/A#ifdef POSIX_REGEXPS
2N/A match = (regexec(&data->preg, name, 0, NULL, 0) == 0);
2N/A#endif
2N/A#ifdef BSD_REGEXPS
2N/A match = (re_exec(name) != 0);
2N/A#endif
2N/A if (match) {
2N/A if (data->n_names == data->sz_names) {
2N/A int new_sz = data->sz_names * 2;
2N/A char **new_names = realloc(data->names,
2N/A new_sz * sizeof(char *));
2N/A if (new_names) {
2N/A data->names = new_names;
2N/A data->sz_names = new_sz;
2N/A } else {
2N/A data->malloc_failed = 1;
2N/A free(name);
2N/A return;
2N/A }
2N/A }
2N/A data->names[data->n_names++] = name;
2N/A } else
2N/A free(name);
2N/A}
2N/A
2N/Astatic void get_pols_iter(void *data, osa_policy_ent_t entry)
2N/A{
2N/A char *name;
2N/A
2N/A if ((name = strdup(entry->name)) == NULL)
2N/A return;
2N/A get_either_iter(data, name);
2N/A}
2N/A
2N/Astatic void get_princs_iter(void *data, krb5_principal princ)
2N/A{
2N/A struct iter_data *id = (struct iter_data *) data;
2N/A char *name;
2N/A
2N/A if (krb5_unparse_name(id->context, princ, &name) != 0)
2N/A return;
2N/A get_either_iter(data, name);
2N/A}
2N/A
2N/Astatic kadm5_ret_t kadm5_get_either(int princ,
2N/A void *server_handle,
2N/A char *exp,
2N/A char ***princs,
2N/A int *count)
2N/A{
2N/A struct iter_data data;
2N/A#ifdef BSD_REGEXPS
2N/A char *msg;
2N/A#endif
2N/A char *regexp;
2N/A int i, ret;
2N/A kadm5_server_handle_t handle = server_handle;
2N/A
2N/A *princs = NULL;
2N/A *count = 0;
2N/A if (exp == NULL)
2N/A exp = "*";
2N/A
2N/A CHECK_HANDLE(server_handle);
2N/A
2N/A if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL,
2N/A &regexp)) != KADM5_OK)
2N/A return ret;
2N/A
2N/A if (
2N/A#ifdef SOLARIS_REGEXPS
2N/A ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
2N/A#endif
2N/A#ifdef POSIX_REGEXPS
2N/A ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
2N/A#endif
2N/A#ifdef BSD_REGEXPS
2N/A ((msg = (char *) re_comp(regexp)) != NULL)
2N/A#endif
2N/A )
2N/A {
2N/A /* XXX syslog msg or regerr(regerrno) */
2N/A free(regexp);
2N/A return EINVAL;
2N/A }
2N/A
2N/A data.n_names = 0;
2N/A data.sz_names = 10;
2N/A data.malloc_failed = 0;
2N/A data.names = malloc(sizeof(char *) * data.sz_names);
2N/A if (data.names == NULL) {
2N/A free(regexp);
2N/A return ENOMEM;
2N/A }
2N/A
2N/A if (princ) {
2N/A data.context = handle->context;
2N/A ret = kdb_iter_entry(handle, exp, get_princs_iter, (void *) &data);
2N/A } else {
2N/A ret = krb5_db_iter_policy(handle->context, exp, get_pols_iter, (void *)&data);
2N/A }
2N/A
2N/A free(regexp);
2N/A#ifdef POSIX_REGEXPS
2N/A regfree(&data.preg);
2N/A#endif
2N/A if ( !ret && data.malloc_failed)
2N/A ret = ENOMEM;
2N/A if ( ret ) {
2N/A for (i = 0; i < data.n_names; i++)
2N/A free(data.names[i]);
2N/A free(data.names);
2N/A return ret;
2N/A }
2N/A
2N/A *princs = data.names;
2N/A *count = data.n_names;
2N/A return KADM5_OK;
2N/A}
2N/A
2N/Akadm5_ret_t kadm5_get_principals(void *server_handle,
2N/A char *exp,
2N/A char ***princs,
2N/A int *count)
2N/A{
2N/A return kadm5_get_either(1, server_handle, exp, princs, count);
2N/A}
2N/A
2N/Akadm5_ret_t kadm5_get_policies(void *server_handle,
2N/A char *exp,
2N/A char ***pols,
2N/A int *count)
2N/A{
2N/A return kadm5_get_either(0, server_handle, exp, pols, count);
2N/A}