File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / alias.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 10:46:12 2013 UTC (10 years, 11 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_8p0, v1_8_8, v1_8_7p0, v1_8_7, HEAD
1.8.7

    1: /*
    2:  * Copyright (c) 2004-2005, 2007-2013
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   17:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   18:  */
   19: 
   20: #include <config.h>
   21: 
   22: #include <sys/types.h>
   23: #include <stdio.h>
   24: #ifdef STDC_HEADERS
   25: # include <stdlib.h>
   26: # include <stddef.h>
   27: #else
   28: # ifdef HAVE_STDLIB_H
   29: #  include <stdlib.h>
   30: # endif
   31: #endif /* STDC_HEADERS */
   32: #ifdef HAVE_STRING_H
   33: # include <string.h>
   34: #endif /* HAVE_STRING_H */
   35: #ifdef HAVE_STRINGS_H
   36: # include <strings.h>
   37: #endif /* HAVE_STRING_H */
   38: #ifdef HAVE_UNISTD_H
   39: # include <unistd.h>
   40: #endif /* HAVE_UNISTD_H */
   41: #include <errno.h>
   42: 
   43: #include "sudoers.h"
   44: #include "parse.h"
   45: #include "redblack.h"
   46: #include <gram.h>
   47: 
   48: /*
   49:  * Globals
   50:  */
   51: struct rbtree *aliases;
   52: 
   53: /*
   54:  * Comparison function for the red-black tree.
   55:  * Aliases are sorted by name with the type used as a tie-breaker.
   56:  */
   57: int
   58: alias_compare(const void *v1, const void *v2)
   59: {
   60:     const struct alias *a1 = (const struct alias *)v1;
   61:     const struct alias *a2 = (const struct alias *)v2;
   62:     int res;
   63:     debug_decl(alias_compare, SUDO_DEBUG_ALIAS)
   64: 
   65:     if (v1 == NULL)
   66: 	res = -1;
   67:     else if (v2 == NULL)
   68: 	res = 1;
   69:     else if ((res = strcmp(a1->name, a2->name)) == 0)
   70: 	res = a1->type - a2->type;
   71:     debug_return_int(res);
   72: }
   73: 
   74: /*
   75:  * Search the tree for an alias with the specified name and type.
   76:  * Returns a pointer to the alias structure or NULL if not found.
   77:  * Caller is responsible for calling alias_put() on the returned
   78:  * alias to mark it as unused.
   79:  */
   80: struct alias *
   81: alias_get(char *name, int type)
   82: {
   83:     struct alias key;
   84:     struct rbnode *node;
   85:     struct alias *a = NULL;
   86:     debug_decl(alias_get, SUDO_DEBUG_ALIAS)
   87: 
   88:     key.name = name;
   89:     key.type = type;
   90:     if ((node = rbfind(aliases, &key)) != NULL) {
   91: 	/*
   92: 	 * Check whether this alias is already in use.
   93: 	 * If so, we've detected a loop.  If not, set the flag,
   94: 	 * which the caller should clear with a call to alias_put().
   95: 	 */
   96: 	a = node->data;
   97: 	if (a->used) {
   98: 	    errno = ELOOP;
   99: 	    debug_return_ptr(NULL);
  100: 	}
  101: 	a->used = true;
  102:     } else {
  103: 	errno = ENOENT;
  104:     }
  105:     debug_return_ptr(a);
  106: }
  107: 
  108: /*
  109:  * Clear the "used" flag in an alias once the caller is done with it.
  110:  */
  111: void
  112: alias_put(struct alias *a)
  113: {
  114:     debug_decl(alias_put, SUDO_DEBUG_ALIAS)
  115:     a->used = false;
  116:     debug_return;
  117: }
  118: 
  119: /*
  120:  * Add an alias to the aliases redblack tree.
  121:  * Returns NULL on success and an error string on failure.
  122:  */
  123: char *
  124: alias_add(char *name, int type, struct member *members)
  125: {
  126:     static char errbuf[512];
  127:     struct alias *a;
  128:     debug_decl(alias_add, SUDO_DEBUG_ALIAS)
  129: 
  130:     a = ecalloc(1, sizeof(*a));
  131:     a->name = name;
  132:     a->type = type;
  133:     /* a->used = false; */
  134:     list2tq(&a->members, members);
  135:     if (rbinsert(aliases, a)) {
  136: 	snprintf(errbuf, sizeof(errbuf), N_("Alias `%s' already defined"), name);
  137: 	alias_free(a);
  138: 	debug_return_str(errbuf);
  139:     }
  140:     debug_return_str(NULL);
  141: }
  142: 
  143: /*
  144:  * Apply a function to each alias entry and pass in a cookie.
  145:  */
  146: void
  147: alias_apply(int (*func)(void *, void *), void *cookie)
  148: {
  149:     debug_decl(alias_apply, SUDO_DEBUG_ALIAS)
  150: 
  151:     rbapply(aliases, func, cookie, inorder);
  152: 
  153:     debug_return;
  154: }
  155: 
  156: /*
  157:  * Returns true if there are no aliases, else false.
  158:  */
  159: bool
  160: no_aliases(void)
  161: {
  162:     debug_decl(no_aliases, SUDO_DEBUG_ALIAS)
  163:     debug_return_bool(rbisempty(aliases));
  164: }
  165: 
  166: /*
  167:  * Free memory used by an alias struct and its members.
  168:  */
  169: void
  170: alias_free(void *v)
  171: {
  172:     struct alias *a = (struct alias *)v;
  173:     struct member *m;
  174:     struct sudo_command *c;
  175:     void *next;
  176:     debug_decl(alias_free, SUDO_DEBUG_ALIAS)
  177: 
  178:     efree(a->name);
  179:     for (m = a->members.first; m != NULL; m = next) {
  180: 	next = m->next;
  181: 	if (m->type == COMMAND) {
  182: 		c = (struct sudo_command *) m->name;
  183: 		efree(c->cmnd);
  184: 		efree(c->args);
  185: 	}
  186: 	efree(m->name);
  187: 	efree(m);
  188:     }
  189:     efree(a);
  190: 
  191:     debug_return;
  192: }
  193: 
  194: /*
  195:  * Find the named alias, remove it from the tree and return it.
  196:  */
  197: struct alias *
  198: alias_remove(char *name, int type)
  199: {
  200:     struct rbnode *node;
  201:     struct alias key;
  202:     debug_decl(alias_remove, SUDO_DEBUG_ALIAS)
  203: 
  204:     key.name = name;
  205:     key.type = type;
  206:     if ((node = rbfind(aliases, &key)) == NULL) {
  207: 	errno = ENOENT;
  208: 	return NULL;
  209:     }
  210:     debug_return_ptr(rbdelete(aliases, node));
  211: }
  212: 
  213: void
  214: init_aliases(void)
  215: {
  216:     debug_decl(init_aliases, SUDO_DEBUG_ALIAS)
  217: 
  218:     if (aliases != NULL)
  219: 	rbdestroy(aliases, alias_free);
  220:     aliases = rbcreate(alias_compare);
  221: 
  222:     debug_return;
  223: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>