lib/libaccess/lasdns.cpp | 283 ++++++++++++++++++++++------------------------- 1 file changed, 133 insertions(+), 150 deletions(-)
New commits: commit 8a9684ff9cadddc58de3a849c1e875955ea16128 Author: Noriko Hosoi nhosoi@totoro.usersys.redhat.com Date: Fri Nov 9 10:52:38 2012 -0800
Trac Ticket #311 - IP lookup failing with multiple DNS entries
https://fedorahosted.org/389/ticket/311
Bug description: DNS keyword in ACI only accepted an FQDN returned from gethostbyaddr. If an alias hostname was set in an ACI, a request sent from the host was treated as the one from the primary hostname and it failed to get the expected access rights.
Fix description: This patch turns the "dns" keyword covers the alias hostnames, as well. In addition to the primary hostname, by setting the secondary hostnames as dns, clients requests would obtain the expected access rights. When an IP address is associated with multiple hostnames (primary: hostA, aliases: hostB and hostC), they could be listed, for instance, in an aci as follows: aci: (targetattr = "*") (version 3.0;acl "dns example";allow (all) dns="hostA.example.com" or dns="hostB.example.com" or dns="hostC. example.com";)
diff --git a/lib/libaccess/lasdns.cpp b/lib/libaccess/lasdns.cpp index e4032f1..de8e624 100644 --- a/lib/libaccess/lasdns.cpp +++ b/lib/libaccess/lasdns.cpp @@ -137,14 +137,13 @@ LASDnsMatch(char *token, LASDnsContext_t *context) 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; + size_t delimiter; /* length of valid tokeni */ + char token[256]; /* max length dns name */ + int i; + int ipcnt = 0; + char **p; pool_handle_t *pool; - PRStatus error=PR_SUCCESS; + PRStatus error=PR_SUCCESS; char buffer[PR_NETDB_BUF_SIZE]; #ifdef UTEST struct hostent *he, host; @@ -154,164 +153,146 @@ LASDnsBuild(NSErr_t *errp, char *attr_pattern, LASDnsContext_t *context, int ali char *end_attr_pattern;
if (attr_pattern == NULL) { - nserrGenerate(errp, ACLERRINVAL, ACLERR4770, ACL_Program, 1, - XP_GetAdminStr(DBT_lasdnsbuildInvalidAttributePattern_)); + nserrGenerate(errp, ACLERRINVAL, ACLERR4770, ACL_Program, 1, + XP_GetAdminStr(DBT_lasdnsbuildInvalidAttributePattern_)); return LAS_EVAL_INVALID; }
context->Table = PR_NewHashTable(0, - PR_HashCaseString, - PR_CompareCaseStrings, - PR_CompareValues, - &ACLPermAllocOps, - NULL); + 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_)); + nserrGenerate(errp, ACLERRNOMEM, ACLERR4700, ACL_Program, 1, + XP_GetAdminStr(DBT_lasdnsbuildUnableToAllocateHashT_)); return LAS_EVAL_INVALID; }
end_attr_pattern = attr_pattern + strlen(attr_pattern); 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; - } + 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 */ + /* Skip any white space after the token */ attr_pattern += delimiter; if (attr_pattern < end_attr_pattern) { 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. - */ + * 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 (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) { + void *iter = NULL; + int addrcnt = 0; + PRNetAddr *netaddr = (PRNetAddr *)PERM_CALLOC(sizeof(PRNetAddr)); + PRAddrInfo *infop = PR_GetAddrInfoByName(token, + PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME)); + if (!netaddr) { + if (infop) { + PR_FreeAddrInfo(infop); + } + return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */ + } + if (!infop) { + if (netaddr) { + PERM_FREE(netaddr); + } + return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */ + } + /* need to count the address, first */ + while ((iter = PR_EnumerateAddrInfo(iter, infop, 0, netaddr))) { + addrcnt++; + } + if (0 == addrcnt) { + PERM_FREE(netaddr); + PR_FreeAddrInfo(infop); + return LAS_EVAL_NEED_MORE_INFO; /* hostname not known to dns? */ + } + iter = NULL; /* from the beginning */ + memset(netaddr, 0, sizeof(PRNetAddr)); + for (i = 0; i < addrcnt; i++) { + iter = PR_EnumerateAddrInfo( iter, infop, 0, netaddr ); + if (NULL == iter) { + break; + } + error = PR_GetHostByAddr(netaddr, buffer, + PR_NETDB_BUF_SIZE, &host); + if (error == PR_SUCCESS) { + he = &host; + } else { + continue; + } + 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(netaddr); + PR_FreeAddrInfo(infop); + 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); - ipaddrs = NULL; - - } /* if he */ - - - } /* if aliasflg */ - - } /* else - single hostname */ - - + 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(netaddr); + PR_FreeAddrInfo(infop); + return LAS_EVAL_INVALID; + } + } + } + } /* for (i = 0; i < addrcnt; i++) */ + PERM_FREE(netaddr); + PR_FreeAddrInfo(infop); + } /* if aliasflg */ + } /* else - single hostname */ } while ((attr_pattern != NULL) && - (attr_pattern[0] != '\0') && - (delimiter != 0)); + (attr_pattern[0] != '\0') && + (delimiter != 0));
return 0; } @@ -363,18 +344,20 @@ int LASDnsEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
*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 (strcmp(attr_name, "dns") == 0) { + /* Enable aliasflg for "dns", which allows "dns" hostname to look up + * DSN hash table using the primary hostname. */ + aliasflg = 1; + } 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; + 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. */
389-commits@lists.fedoraproject.org