| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /* lasdns.c
- * This file contains the DNS LAS code.
- */
- #include <stdio.h>
- #include <string.h>
- #ifdef XP_WIN32
- /* #include <winsock2.h> */
- #include <winsock.h>
- #else
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #endif
- #include <netsite.h>
- extern "C" {
- #include <prnetdb.h>
- }
- #include <base/plist.h>
- #include <base/pool.h>
- #include <libaccess/nserror.h>
- #include <libaccess/nsauth.h>
- #include <libaccess/acl.h>
- #include "aclpriv.h"
- #include <libaccess/aclproto.h>
- #include <libaccess/las.h>
- #include "lasdns.h"
- #include "aclutil.h"
- #include "aclcache.h"
- #include "permhash.h"
- #include <libaccess/dbtlibaccess.h>
- #include <libaccess/aclerror.h>
- #include "access_plhash.h"
- extern "C" {
- #include <nspr.h>
- }
- #ifdef UTEST
- extern int LASDnsGetDns(char **dnsv);
- #endif
- /* LASDnsMatch
- * Given an array of fully-qualified dns names, tries to match them
- * against a given hash table.
- * INPUT
- * dns DNS string
- * context pointer to an LAS DNS context structure
- *
- * In our usage, this context is derived from
- * an acllist cache, which is a representation of
- * of some global acis--in other words it's a global thing
- * shared between threads--hence the use
- * of the "read-only" hash lookup routines here.
- */
- int
- LASDnsMatch(char *token, LASDnsContext_t *context)
- {
- /* Test for the unusual case where "*" is allowed */
- if (ACL_HashTableLookup_const(context->Table, "*"))
- return LAS_EVAL_TRUE;
- /* Start with the full name. Then strip off each component
- * leaving the remainder starting with a period. E.g.
- * splash.mcom.com
- * .mcom.com
- * .com
- * Search the hash table for each remaining portion. Remember that
- * wildcards were put in with the leading period intact.
- */
- do {
- if (ACL_HashTableLookup_const(context->Table, token))
- return LAS_EVAL_TRUE;
- token = strchr(&token[1], '.');
- } while (token != NULL);
- return LAS_EVAL_FALSE;
- }
- /* LASDNSBuild
- * Builds a hash table of all the hostnames provided (plus their aliases
- * if aliasflg is true). Wildcards are only permitted in the leftmost
- * field. They're represented in the hash table by a leading period.
- * E.g. ".mcom.com".
- *
- * RETURNS Zero on success, else LAS_EVAL_INVALID
- */
- int
- LASDnsBuild(NSErr_t *errp, char *attr_pattern, LASDnsContext_t *context, int aliasflg)
- {
- size_t delimiter; /* length of valid token */
- char token[256]; /* max length dns name */
- int i;
- int ipcnt = 0;
- char **p;
- unsigned long *ipaddrs=0;
- pool_handle_t *pool;
- PRStatus error=PR_SUCCESS;
- char buffer[PR_NETDB_BUF_SIZE];
- #ifdef UTEST
- struct hostent *he, host;
- #else
- PRHostEnt *he, host;
- #endif
- context->Table = PR_NewHashTable(0,
- PR_HashCaseString,
- PR_CompareCaseStrings,
- PR_CompareValues,
- &ACLPermAllocOps,
- NULL);
- pool = pool_create();
- context->pool = pool;
- if ((!context->Table) || (!context->pool)) {
- nserrGenerate(errp, ACLERRNOMEM, ACLERR4700, ACL_Program, 1,
- XP_GetAdminStr(DBT_lasdnsbuildUnableToAllocateHashT_));
- return LAS_EVAL_INVALID;
- }
- do {
- size_t maxsize = sizeof(token);
- /* Get a single hostname from the pattern string */
- delimiter = strcspn(attr_pattern, ", \t");
- if (delimiter >= maxsize) {
- delimiter = maxsize-1;
- }
- PL_strncpyz(token, attr_pattern, delimiter + 1);
- token[delimiter] = '\0';
- /* Skip any white space after the token */
- attr_pattern += delimiter;
- attr_pattern += strspn(attr_pattern, ", \t");
- /* If there's a wildcard, strip it off but leave the "."
- * Can't have aliases for a wildcard pattern.
- * Treat "*" as a special case. If so, go ahead and hash it.
- */
- if (token[0] == '*') {
- if (token[1] != '\0') {
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, &token[1]), (void *)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4710, ACL_Program, 2,
- XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
- return LAS_EVAL_INVALID;
- }
- } else {
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, token), (void *)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4720, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
- return LAS_EVAL_INVALID;
- }
- }
- } else {
- /* This is a single hostname add it to the hash table */
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, &token[0]), (void *)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4730, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), token);
- return LAS_EVAL_INVALID;
- }
- if (aliasflg) {
- /* memset(buffer, '\0', PR_NETDB_BUF_SIZE);
- */
- #ifdef UTEST
- he = gethostbyname(token);
- #else
- error = PR_GetHostByName(token,
- buffer,
- PR_NETDB_BUF_SIZE,
- &host);
- if (error == PR_SUCCESS) he = &host;
- else he = NULL;
- #endif
- if (he) {
- /* Make a copy of the list of IP addresses if any */
- if (he->h_addr_list && he->h_addr_list[0]) {
-
- /* Count the IP addresses */
- for (p = he->h_addr_list, ipcnt = 0; *p; ++p) {
- ++ipcnt;
- }
-
- /* Allocate space */
- ipaddrs = (unsigned long *)PERM_MALLOC(ipcnt * sizeof(unsigned long));
-
- /* Copy IP addresses */
- for (i = 0; i < ipcnt; ++i) {
- ipaddrs[i] = 0;
- memcpy((void *)&ipaddrs[i], he->h_addr_list[i], 4);
- }
- }
-
- /* Add each of the aliases to the list */
- if (he->h_aliases && he->h_aliases[0]) {
-
- for (p = he->h_aliases; *p; ++p) {
- /* Add it to the hash table */
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, *p), (void*)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4740, ACL_Program, 2,
- XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), *p);
- PERM_FREE(ipaddrs);
- return LAS_EVAL_INVALID;
- }
- }
- }
-
- for (i = 0; i < ipcnt; ++i) {
- #ifdef UTEST
- he = gethostbyaddr((char *)&ipaddrs[i], 4, AF_INET);
- #else
- error = PR_GetHostByAddr((PRNetAddr *)&ipaddrs[i],
- buffer,
- PR_NETDB_BUF_SIZE,
- &host);
- if (error == PR_SUCCESS) he = &host;
- else he = NULL;
- #endif
- if (he) {
- if (he->h_name) {
- /* Add it to the hash table */
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, he->h_name),
- (void *)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4750, ACL_Program, 2,
- XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), he->h_name);
- PERM_FREE(ipaddrs);
- return LAS_EVAL_INVALID;
- }
- }
-
- if (he->h_aliases && he->h_aliases[0]) {
- for (p = he->h_aliases; *p; ++p) {
- /* Add it to the hash table */
- if (!PR_HashTableAdd(context->Table, pool_strdup(pool, *p), (void *)-1)) {
- nserrGenerate(errp, ACLERRFAIL, ACLERR4760, ACL_Program, 2,
- XP_GetAdminStr(DBT_lasdnsbuildUnableToAddKeySN_), *p);
- PERM_FREE(ipaddrs);
- return LAS_EVAL_INVALID;
- }
- }
- }
- }
- }
- PERM_FREE(ipaddrs);
- } /* if he */
- } /* if aliasflg */
- } /* else - single hostname */
- } while ((attr_pattern != NULL) &&
- (attr_pattern[0] != '\0') &&
- (delimiter != 0));
- return 0;
- }
- /* LASDnsFlush
- * Given the address of a las_cookie for a DNS expression entry, frees up
- * all allocated memory for it. This includes the hash table, plus the
- * context structure.
- */
- void
- LASDnsFlush(void **las_cookie)
- {
- if (*las_cookie == NULL)
- return;
- pool_destroy(((LASDnsContext_t *)*las_cookie)->pool);
- PR_HashTableDestroy(((LASDnsContext_t *)*las_cookie)->Table);
- PERM_FREE(*las_cookie);
- *las_cookie = NULL;
- return;
- }
- /*
- * LASDnsEval
- * INPUT
- * attr_name The string "dns" - in lower case.
- * comparator CMP_OP_EQ or CMP_OP_NE only
- * attr_pattern A comma-separated list of DNS names
- * Any segment(s) in a DNS name can be wildcarded using
- * "*". Note that this is not a true Regular Expression
- * form.
- * *cachable Always set to ACL_INDEF_CACHE
- * subject Subject property list
- * resource Resource property list
- * auth_info Authentication info, if any
- * RETURNS
- * ret code The usual LAS return codes.
- */
- int LASDnsEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
- char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie,
- PList_t subject, PList_t resource,
- PList_t auth_info, PList_t global_auth)
- {
- int result;
- int aliasflg;
- char *my_dns;
- LASDnsContext_t *context = NULL;
- int rv;
- *cachable = ACL_INDEF_CACHABLE;
- if (strcmp(attr_name, "dns") == 0)
- aliasflg = 0;
- else if (strcmp(attr_name, "dnsalias") == 0)
- aliasflg = 1;
- else {
- nserrGenerate(errp, ACLERRINVAL, ACLERR4800, ACL_Program, 2, XP_GetAdminStr(DBT_lasDnsBuildReceivedRequestForAtt_), attr_name);
- return LAS_EVAL_INVALID;
- }
- if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
- nserrGenerate(errp, ACLERRINVAL, ACLERR4810, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalIllegalComparatorDN_), comparator_string(comparator));
- return LAS_EVAL_INVALID;
- }
- /* If this is the first time through, build the pattern tree first. */
- if (*LAS_cookie == NULL) {
- ACL_CritEnter();
- if (*LAS_cookie == NULL) { /* Must check again */
- *LAS_cookie = context =
- (LASDnsContext_t *)PERM_MALLOC(sizeof(LASDnsContext_t));
- if (context == NULL) {
- nserrGenerate(errp, ACLERRNOMEM, ACLERR4820, ACL_Program, 1, XP_GetAdminStr(DBT_lasdnsevalUnableToAllocateContex_));
- ACL_CritExit();
- return LAS_EVAL_FAIL;
- }
- context->Table = NULL;
- LASDnsBuild(errp, attr_pattern, context, aliasflg);
- }
- ACL_CritExit();
- } else
- context = (LASDnsContext *) *LAS_cookie;
- /* Call the DNS attribute getter */
- #ifdef UTEST
- LASDnsGetDns(&my_dns); /* gets stuffed on return */
- #else
- rv = ACL_GetAttribute(errp, ACL_ATTR_DNS, (void **)&my_dns,
- subject, resource, auth_info, global_auth);
- if (rv != LAS_EVAL_TRUE) {
- if (subject || resource) {
- char rv_str[16];
- /* Don't ereport if called from ACL_CachableAclList */
- sprintf(rv_str, "%d", rv);
- nserrGenerate(errp, ACLERRINVAL, ACLERR4830, ACL_Program, 2, XP_GetAdminStr(DBT_lasdnsevalUnableToGetDnsErrorDN_), rv_str);
- }
- return LAS_EVAL_FAIL;
- }
- #endif
- result = LASDnsMatch(my_dns, context);
- if (comparator == CMP_OP_NE) {
- if (result == LAS_EVAL_FALSE)
- return LAS_EVAL_TRUE;
- else if (result == LAS_EVAL_TRUE)
- return LAS_EVAL_FALSE;
- }
- return (result);
- }
|