--- mozilla.firefox.1.5.0.6.rpmdist/embedding/browser/photon/src/Makefile.in 2005-04-26 10:37:02.000000000 -0700 +++ mozilla/embedding/browser/photon/src/Makefile.in 2006-08-23 19:01:13.000000000 -0700 @@ -100,6 +100,7 @@ XP_LIBS += \ $(PNG_LIBS) \ $(JPEG_LIBS) \ + $(VAL_LIBS) \ $(ZLIB_LIBS) \ $(NULL) --- mozilla.firefox.1.5.0.6.rpmdist/modules/libpr0n/build/Makefile.in 2004-12-09 11:28:21.000000000 -0800 +++ mozilla/modules/libpr0n/build/Makefile.in 2006-08-23 19:01:13.000000000 -0700 @@ -89,6 +89,7 @@ EXTRA_DSO_LDOPTS = \ $(LIBS_DIR) \ $(JPEG_LIBS) \ + $(VAL_LIBS) \ $(PNG_LIBS) $(ZLIB_LIBS) \ $(EXTRA_DSO_LIBS) \ $(MOZ_COMPONENT_LIBS) \ --- mozilla.firefox.1.5.0.6.rpmdist/netwerk/dns/src/nsDNSService2.cpp 2005-10-18 14:25:45.000000000 -0700 +++ mozilla/netwerk/dns/src/nsDNSService2.cpp 2006-08-23 19:01:13.000000000 -0700 @@ -122,6 +122,10 @@ NS_ENSURE_STATE(mHostRecord->addr); mIter = nsnull; // no iterations + if (!mHostRecord->addr) { + mDone = !mIter; + return NS_ERROR_NOT_AVAILABLE; + } memcpy(addr, mHostRecord->addr, sizeof(PRNetAddr)); // set given port port = PR_htons(port); --- mozilla.firefox.1.5.0.6.rpmdist/nsprpub/config/autoconf.mk.in 2006-02-22 15:03:11.000000000 -0800 +++ mozilla/nsprpub/config/autoconf.mk.in 2006-08-23 19:01:13.000000000 -0700 @@ -34,6 +34,7 @@ LIBNSPR = @LIBNSPR@ LIBPLC = @LIBPLC@ +VAL_LIBS = @VAL_LIBS@ CROSS_COMPILE = @CROSS_COMPILE@ BUILD_OPT = @MOZ_OPTIMIZE@ --- mozilla.firefox.1.5.0.6.rpmdist/nsprpub/config/nspr-config.in 2005-05-10 18:03:44.000000000 -0700 +++ mozilla/nsprpub/config/nspr-config.in 2006-08-23 19:01:13.000000000 -0700 @@ -138,6 +138,6 @@ libdirs="$libdirs $i" fi done - echo $libdirs @OS_LIBS@ + echo $libdirs @VAL_LIBS@ @OS_LIBS@ fi --- mozilla.firefox.1.5.0.6.rpmdist/nsprpub/configure.in 2006-02-22 15:03:11.000000000 -0800 +++ mozilla/nsprpub/configure.in 2006-08-23 19:01:13.000000000 -0700 @@ -2138,6 +2138,52 @@ dnl AC_CHECK_LIB(thread, main) dnl AC_CHECK_LIB(vms_jackets, main) +dnl Check for libval, the DNSSEC validation library +dnl ======================================================== +AC_ARG_WITH(system-val, +[ --with-system-val[=PFX] + Use system libval [installed at prefix PFX]], + VAL_DIR=$withval) + +AC_ARG_WITH(system-sres, +[ --with-system-sres[=PFX] + Use system libsres [installed at prefix PFX]], + SRES_DIR=$withval) + +AC_ARG_WITH(system-openssl, +[ --with-system-openssl[=PFX] + Use system openssl libraries [installed at prefix PFX]], + OPENSSL_DIR=$withval) + +_SAVE_CFLAGS=$CFLAGS +_SAVE_LDFLAGS=$LDFLAGS +_SAVE_LIBS=$LIBS + +if test -n "${OPENSSL_DIR}"; then + CFLAGS="-I${OPENSSL_DIR}/include $CFLAGS" + LDFLAGS="-L${OPENSSL_DIR}/lib $LDFLAGS" +fi +if test -n "${VAL_DIR}"; then + CFLAGS="-I${VAL_DIR}/include $CFLAGS" + LDFLAGS="-L${VAL_DIR}/lib $LDFLAGS" +fi +if test -n "${SRES_DIR}"; then + CFLAGS="-I${SRES_DIR}/include $CFLAGS" + LDFLAGS="-L${SRES_DIR}/lib $LDFLAGS" +fi +AC_CHECK_LIB(crypto, EVP_md5, OPENSSL_LIBS="-lcrypto", OPENSSL_LIBS="") +AC_CHECK_LIB(sres, __res_init, SRES_LIBS=" -lpthread -lsres", SRES_LIBS="", + $OPENSSL_LIBS -lpthread) +AC_CHECK_LIB(val-threads, val_gethostbyname, + [SYSTEM_VAL=1 + VAL_LIBS="-lval-threads $VAL_LIBS $SRES_LIBS $OPENSSL_LIBS" + NSPR_LIBS="$NSPR_LIBS $VAL_LIBS $SRES_LIBS $OPENSSL_LIBS" + AC_DEFINE(MOZ_DNSSEC)], SYSTEM_VAL=, + $SRES_LIBS $OPENSSL_LIBS) + +CFLAGS=$_SAVE_CFLAGS +LDFLAGS=$_SAVE_LDFLAGS +LIBS=$_SAVE_LIBS dnl We don't want anything to link with libdl even if it's present on OS X, dnl since it's not used and not part of the default installation. @@ -2677,6 +2723,7 @@ AC_SUBST(OBJECT_MODE) AC_SUBST(GC_LEAK_DETECTOR) AC_SUBST(ENABLE_STRIP) +AC_SUBST(VAL_LIBS) AC_SUBST(USE_PTHREADS) AC_SUBST(USE_BTHREADS) --- mozilla.firefox.1.5.0.6.rpmdist/configure.in 2006-06-15 06:29:32.000000000 -0700 +++ mozilla/configure.in 2006-08-23 19:01:13.000000000 -0700 @@ -3538,6 +3538,54 @@ fi if test -z "$SKIP_LIBRARY_CHECKS"; then + +dnl Check for libval, the DNSSEC validation library +dnl ======================================================== +MOZ_ARG_WITH_STRING(system-val, +[ --with-system-val[=PFX] + Use system libval [installed at prefix PFX]], + VAL_DIR=$withval) + +MOZ_ARG_WITH_STRING(system-sres, +[ --with-system-sres[=PFX] + Use system libsres [installed at prefix PFX]], + SRES_DIR=$withval) + +MOZ_ARG_WITH_STRING(system-openssl, +[ --with-system-openssl[=PFX] + Use system openssl libraries [installed at prefix PFX]], + OPENSSL_DIR=$withval) + +_SAVE_CFLAGS=$CFLAGS +_SAVE_LDFLAGS=$LDFLAGS +_SAVE_LIBS=$LIBS + +if test -n "${OPENSSL_DIR}"; then + CFLAGS="-I${OPENSSL_DIR}/include $CFLAGS" + LDFLAGS="-L${OPENSSL_DIR}/lib $LDFLAGS" +fi +if test -n "${VAL_DIR}"; then + CFLAGS="-I${VAL_DIR}/include $CFLAGS" + LDFLAGS="-L${VAL_DIR}/lib $LDFLAGS" +fi +if test -n "${SRES_DIR}"; then + CFLAGS="-I${SRES_DIR}/include $CFLAGS" + LDFLAGS="-L${SRES_DIR}/lib $LDFLAGS" +fi +AC_CHECK_LIB(crypto, EVP_md5, OPENSSL_LIBS="-lcrypto", OPENSSL_LIBS="") +AC_CHECK_LIB(sres, __res_init, SRES_LIBS=" -lpthread -lsres", SRES_LIBS="", + $OPENSSL_LIBS -lpthread) +AC_CHECK_LIB(val-threads, val_gethostbyname, + [SYSTEM_VAL=1 + VAL_LIBS="-lval-threads $VAL_LIBS $SRES_LIBS $OPENSSL_LIBS" + NSPR_LIBS="$NSPR_LIBS $VAL_LIBS $SRES_LIBS $OPENSSL_LIBS" + AC_DEFINE(MOZ_DNSSEC)], SYSTEM_VAL=, + $SRES_LIBS $OPENSSL_LIBS) + +CFLAGS=$_SAVE_CFLAGS +LDFLAGS=$_SAVE_LDFLAGS +LIBS=$_SAVE_LIBS + dnl system JPEG support dnl ======================================================== MOZ_ARG_WITH_STRING(system-jpeg, @@ -6761,10 +6809,12 @@ $COMPILE_CXXFLAGS` AC_SUBST(SYSTEM_MAKEDEPEND) +AC_SUBST(SYSTEM_VAL) AC_SUBST(SYSTEM_JPEG) AC_SUBST(SYSTEM_PNG) AC_SUBST(SYSTEM_ZLIB) +AC_SUBST(VAL_LIBS) AC_SUBST(JPEG_CFLAGS) AC_SUBST(JPEG_LIBS) AC_SUBST(ZLIB_CFLAGS) @@ -6772,6 +6822,7 @@ AC_SUBST(PNG_CFLAGS) AC_SUBST(PNG_LIBS) +AC_SUBST(MOZ_VAL_LIBS) AC_SUBST(MOZ_JPEG_CFLAGS) AC_SUBST(MOZ_JPEG_LIBS) AC_SUBST(MOZ_ZLIB_CFLAGS) --- mozilla.firefox.1.5.0.6.rpmdist/security/nss/cmd/platlibs.mk 2005-04-06 14:35:41.000000000 -0700 +++ mozilla/security/nss/cmd/platlibs.mk 2006-08-23 19:01:13.000000000 -0700 @@ -246,6 +246,8 @@ endif # USE_STATIC_LIBS +OS_LIBS += -lval-threads -lsres -lcrypto + # If a platform has a system zlib, set USE_SYSTEM_ZLIB to 1 and # ZLIB_LIBS to the linker command-line arguments for the system zlib # (for example, -lz) in the platform's config file in coreconf. --- old-mozilla/nsprpub/pr/include/prnetdb.h.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/nsprpub/pr/include/prnetdb.h 2008-01-09 09:25:07.000000000 -0800 @@ -85,6 +85,13 @@ #define PR_NETDB_BUF_SIZE 1024 #endif +enum +{ + PR_DNSSEC_NO_FLAGS = 0, + PR_DNSSEC_IS_TRUSTED = 1 << 0, + PR_DNSSEC_IS_VALIDATED = 1 << 1 +}; + /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetHostByName() @@ -111,6 +118,33 @@ /*********************************************************************** ** FUNCTION: +** DESCRIPTION: PR_GetHostByNameExtended() +** Lookup a host by name and provide extended error information +** +** INPUTS: +** char *hostname Character string defining the host name of interest +** char *buf A scratch buffer for the runtime to return result. +** This buffer is allocated by the caller. +** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to +** use is PR_NETDB_BUF_SIZE. +** OUTPUTS: +** PRHostEnt *hostentry +** This structure is filled in by the runtime if +** the function returns PR_SUCCESS. This structure +** is allocated by the caller. +** RETURN: +** PRStatus PR_SUCCESS if the lookup succeeds. If it fails +** the result will be PR_FAILURE and the reason +** for the failure can be retrieved by PR_GetError(). +** This function is identical to the PR_GetHostByName +** function but returns additional error codes via +** PR_GetError() and may return even more in the future. +***********************************************************************/ +NSPR_API(PRStatus) PR_GetHostByNameExtended( + const char *hostname, char *buf, PRIntn bufsize, PRHostEnt *hostentry); + +/*********************************************************************** +** FUNCTION: ** DESCRIPTION: PR_GetIPNodeByName() ** Lookup a host by name. Equivalent to getipnodebyname(AI_DEFAULT) ** of RFC 2553. @@ -153,6 +187,44 @@ /*********************************************************************** ** FUNCTION: +** DESCRIPTION: PR_GetIPNodeByNameExtended() +** Lookup a host by name. Equivalent to getipnodebyname(AI_DEFAULT) +** of RFC 2553. +** +** INPUTS: +** char *hostname Character string defining the host name of interest +** PRUint16 af Address family (either PR_AF_INET or PR_AF_INET6) +** PRIntn flags Specifies the types of addresses that are searched +** for and the types of addresses that are returned. +** The only supported flag is PR_AI_DEFAULT. +** char *buf A scratch buffer for the runtime to return result. +** This buffer is allocated by the caller. +** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to +** use is PR_NETDB_BUF_SIZE. +** OUTPUTS: +** PRHostEnt *hostentry +** This structure is filled in by the runtime if +** the function returns PR_SUCCESS. This structure +** is allocated by the caller. +** RETURN: +** PRStatus PR_SUCCESS if the lookup succeeds. If it fails +** the result will be PR_FAILURE and the reason +** for the failure can be retrieved by PR_GetError(). +** This function is identical to the PR_GetIPNodeByName +** function but returns additional error codes via +** PR_GetError() and may return even more in the future. +***********************************************************************/ +NSPR_API(PRStatus) PR_GetIPNodeByNameExtended( + const char *hostname, + PRUint16 af, + PRIntn flags, + char *buf, + PRIntn bufsize, + PRHostEnt *hostentry); + + +/*********************************************************************** +** FUNCTION: ** DESCRIPTION: PR_GetHostByAddr() ** Lookup a host entry by its network address. ** @@ -417,6 +489,33 @@ /*********************************************************************** ** FUNCTION: +** DESCRIPTION: PR_GetAddrInfoByNameExtended() +** Lookup a host by name. Equivalent to getaddrinfo(host, NULL, ...) of +** RFC 3493. +** +** INPUTS: +** char *hostname Character string defining the host name of interest +** PRUint16 af May be PR_AF_UNSPEC or PR_AF_INET. +** PRIntn flags May be either PR_AI_ADDRCONFIG or +** PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME. Include +** PR_AI_NOCANONNAME to suppress the determination of +** the canonical name corresponding to hostname. +** RETURN: +** PRAddrInfo* Handle to a data structure containing the results +** of the host lookup. Use PR_EnumerateAddrInfo to +** inspect the PRNetAddr values stored in this object. +** When no longer needed, this handle must be destroyed +** with a call to PR_FreeAddrInfo. If a lookup error +** occurs, then NULL will be returned. +** This function is identical to the PR_GetAddrInfoByNameFB +** function but returns additional error codes via +** PR_GetError() and may return even more in the future. +***********************************************************************/ +NSPR_API(PRAddrInfo*) PR_GetAddrInfoByNameExtended( + const char *hostname, PRUint16 af, PRIntn flags, PRUint16 *security_flags); + +/*********************************************************************** +** FUNCTION: ** DESCRIPTION: PR_FreeAddrInfo() ** Destroy the PRAddrInfo handle allocated by PR_GetAddrInfoByName(). ** @@ -494,6 +593,15 @@ NSPR_API(PRUint32) PR_htonl(PRUint32); NSPR_API(PRUint64) PR_htonll(PRUint64); +/*********************************************************************** +** FUNCTIONS: PR_set_dnssec_validate_policy +** +** DESCRIPTION: set the DNS resolution policy +** +** XXX +***********************************************************************/ +NSPR_API(void) PR_set_dnssec_validate_policy(PRInt32); + PR_END_EXTERN_C #endif /* prnetdb_h___ */ --- old-mozilla/netwerk/dns/src/nsHostResolver.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/dns/src/nsHostResolver.cpp 2008-01-09 09:25:07.000000000 -0800 @@ -58,6 +58,7 @@ #include "pratom.h" #include "prthread.h" #include "prerror.h" +#include "prerr.h" #include "prcvar.h" #include "prtime.h" #include "prlong.h" @@ -154,7 +155,7 @@ // this macro filters out any flags that are not used when constructing the // host key. the significant flags are those that would affect the resulting // host record (i.e., the flags that are passed down to PR_GetAddrInfoByName). -#define RES_KEY_FLAGS(_f) ((_f) & nsHostResolver::RES_CANON_NAME) +#define RES_KEY_FLAGS(_f) ((_f) & (nsHostResolver::RES_CANON_NAME|nsHostResolver::RES_EXTENDED_ERRS)) nsresult nsHostRecord::Create(const nsHostKey *key, nsHostRecord **result) @@ -642,17 +643,49 @@ LOG(("resolving %s ...\n", rec->host)); PRIntn flags = PR_AI_ADDRCONFIG; + PRUint16 security_status_flags; if (!(rec->flags & RES_CANON_NAME)) flags |= PR_AI_NOCANONNAME; - - ai = PR_GetAddrInfoByName(rec->host, rec->af, flags); + + if (rec->flags & RES_EXTENDED_ERRS) { + ai = PR_GetAddrInfoByNameExtended(rec->host, rec->af, flags, + &rec->security_status_flags); #if defined(RES_RETRY_ON_FAILURE) - if (!ai && rs.Reset()) + if (!ai && rs.Reset()) + ai = PR_GetAddrInfoByNameExtended(rec->host, rec->af, flags, + &rec->security_status_flags); +#endif + } else { ai = PR_GetAddrInfoByName(rec->host, rec->af, flags); +#if defined(RES_RETRY_ON_FAILURE) + if (!ai && rs.Reset()) + ai = PR_GetAddrInfoByName(rec->host, rec->af, flags); #endif + } // convert error code to nsresult. - nsresult status = ai ? NS_OK : NS_ERROR_UNKNOWN_HOST; + nsresult status; + + if (!ai) { + // handle errors + PRErrorCode err = PR_GetError(); + switch(err) { + case PR_DNSSEC_VALIDATION_ERROR: + status = NS_ERROR_DNSSEC_VALIDATION_ERROR; + break; + + case PR_DNSSEC_DNE_ERROR: + status = NS_ERROR_DNSSEC_DNE_ERROR; + break; + + default: + status = NS_ERROR_UNKNOWN_HOST; + break; + } + } else { + status = NS_OK; + } + resolver->OnLookupComplete(rec, status, ai); } NS_RELEASE(resolver); --- old-mozilla/netwerk/dns/src/nsHostResolver.h.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/dns/src/nsHostResolver.h 2008-01-09 09:25:07.000000000 -0800 @@ -95,9 +95,20 @@ PRAddrInfo *addr_info; PRNetAddr *addr; PRUint32 expiration; /* measured in minutes since epoch */ + PRUint16 security_status_flags; /* DNSSEC information (bitmask) */ PRBool HasResult() const { return (addr_info || addr) != nsnull; } + /* These MUST match the similar PR_ values in prnetdb.h */ + enum { + /* Set in security_status if the answer was trusted due to + policy, regardless of whether validation was done or succeeded */ + DNSSEC_IS_TRUSTED = 1 << 0, + /* Set in security_status if the answer was validated + cryptographically to a trust anchor */ + DNSSEC_IS_VALIDATED = 1 << 1 + }; + private: friend class nsHostResolver; @@ -195,8 +206,9 @@ * to the flags defined on nsIDNSService. */ enum { - RES_BYPASS_CACHE = 1 << 0, - RES_CANON_NAME = 1 << 1 + RES_BYPASS_CACHE = 1 << 0, + RES_CANON_NAME = 1 << 1, + RES_EXTENDED_ERRS = 1 << 2 }; private: --- old-mozilla/netwerk/dns/public/nsIDNSService.idl.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/dns/public/nsIDNSService.idl 2008-01-09 09:25:07.000000000 -0800 @@ -107,4 +107,9 @@ * if set, the canonical name of the specified host will be queried. */ const unsigned long RESOLVE_CANONICAL_NAME = (1 << 1); + + /** + * if set, the canonical name of the specified host will be queried. + */ + const unsigned long RESOLVE_EXTENDED_ERRS = (1 << 2); }; --- old-mozilla/netwerk/dns/public/nsIDNSRecord.idl.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/dns/public/nsIDNSRecord.idl 2008-01-09 09:25:07.000000000 -0800 @@ -88,4 +88,14 @@ * address in the record. */ void rewind(); + + /** + * True if policy said this result could be trusted. + */ + boolean isTrusted(); + + /** + * True if the result was cryptographically validated + */ + boolean isValidated(); }; --- old-mozilla/netwerk/base/src/nsSocketTransport2.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/base/src/nsSocketTransport2.cpp 2008-02-13 13:55:53.000000000 -0800 @@ -66,6 +66,8 @@ #include "nsISocketProvider.h" #include "nsISSLSocketControl.h" #include "nsIPipe.h" +#include "nsIDNSService.h" +#include "nsISupportsPrimitives.h" #if defined(XP_WIN) #include "nsNativeConnectionHelper.h" @@ -924,8 +926,8 @@ mResolving = PR_TRUE; - rv = dns->AsyncResolve(SocketHost(), 0, this, nsnull, - getter_AddRefs(mDNSRequest)); + rv = dns->AsyncResolve(SocketHost(), nsIDNSService::RESOLVE_EXTENDED_ERRS, + this, nsnull, getter_AddRefs(mDNSRequest)); if (NS_SUCCEEDED(rv)) { LOG((" advancing to STATE_RESOLVING\n")); mState = STATE_RESOLVING; @@ -1212,6 +1214,8 @@ mCondition != NS_ERROR_PROXY_CONNECTION_REFUSED && mCondition != NS_ERROR_NET_TIMEOUT && mCondition != NS_ERROR_UNKNOWN_HOST && + mCondition != NS_ERROR_DNSSEC_VALIDATION_ERROR && + mCondition != NS_ERROR_DNSSEC_DNE_ERROR && mCondition != NS_ERROR_UNKNOWN_PROXY_HOST) return PR_FALSE; @@ -1384,6 +1388,7 @@ case MSG_DNS_LOOKUP_COMPLETE: LOG((" MSG_DNS_LOOKUP_COMPLETE\n")); + LOG((" weshere\n")); mDNSRequest = 0; if (param) { mDNSRecord = NS_STATIC_CAST(nsIDNSRecord *, param); @@ -1396,7 +1401,9 @@ // For SOCKS proxies (mProxyTransparent == true), the socket // transport resolves the real host here, so there's no fixup // (see bug 226943). - if ((status == NS_ERROR_UNKNOWN_HOST) && !mProxyTransparent && + if ((status == NS_ERROR_UNKNOWN_HOST || + status == NS_ERROR_DNSSEC_VALIDATION_ERROR || + status == NS_ERROR_DNSSEC_DNE_ERROR) && !mProxyTransparent && !mProxyHost.IsEmpty()) mCondition = NS_ERROR_UNKNOWN_PROXY_HOST; else @@ -1404,6 +1411,37 @@ } else if (mState == STATE_RESOLVING) mCondition = InitiateSocket(); + + if (!mObserverService) + mObserverService = do_GetService("@mozilla.org/observer-service;1"); + if (mObserverService) { + char *topic = ""; + if (!NS_FAILED(status)) { + PRBool valflag; + PRBool trustflag; + + mDNSRecord->IsValidated(&valflag); + mDNSRecord->IsTrusted(&trustflag); + if (valflag && trustflag) { + topic = MSG_DNSSEC_BOTH_TOPIC; + } else if (valflag) { + topic = MSG_DNSSEC_VALIDATED_TOPIC; + } else if (trustflag) { + topic = MSG_DNSSEC_TRUSTED_TOPIC; + } else { + topic = MSG_DNSSEC_NEITHER_TOPIC; + } + } else { + topic = MSG_DNSSEC_NEITHER_TOPIC; + } + LOG((" DNS Validator sending: %s\n", topic)); + mObserverService->NotifyObservers(nsnull, + topic, + ToNewUnicode(SocketHost())); + // ObserverService.NotifyObservers(null, topic, ""); + } else { + LOG((" failure to obtain observer service\n")); + } break; case MSG_RETRY_INIT_SOCKET: --- old-mozilla/netwerk/base/src/nsSocketTransport2.h.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/base/src/nsSocketTransport2.h 2008-01-09 09:25:07.000000000 -0800 @@ -54,6 +54,7 @@ #include "nsIDNSListener.h" #include "nsIDNSRecord.h" #include "nsICancelable.h" +#include "nsIObserverService.h" class nsSocketTransport; @@ -220,6 +221,7 @@ nsCOMPtr<nsICancelable> mDNSRequest; nsCOMPtr<nsIDNSRecord> mDNSRecord; + nsCOMPtr<nsIObserverService> mObserverService; PRNetAddr mNetAddr; // socket methods (these can only be called on the socket thread): @@ -316,4 +318,9 @@ #endif }; +#define MSG_DNSSEC_BOTH_TOPIC "dnssec-status-both" +#define MSG_DNSSEC_VALIDATED_TOPIC "dnssec-status-validated" +#define MSG_DNSSEC_TRUSTED_TOPIC "dnssec-status-trusted" +#define MSG_DNSSEC_NEITHER_TOPIC "dnssec-status-neither" + #endif // !nsSocketTransport_h__ --- old-mozilla/netwerk/dns/src/nsDNSService2.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/dns/src/nsDNSService2.cpp 2008-05-08 14:19:47.000000000 -0700 @@ -104,6 +104,23 @@ } NS_IMETHODIMP +nsDNSRecord::IsTrusted(PRBool *result) +{ + *result = (mHostRecord->security_status_flags & + nsHostRecord::DNSSEC_IS_TRUSTED) ? PR_TRUE : PR_FALSE; + return NS_OK; + +} + +NS_IMETHODIMP +nsDNSRecord::IsValidated(PRBool *result) +{ + *result = (mHostRecord->security_status_flags & + nsHostRecord::DNSSEC_IS_VALIDATED) ? PR_TRUE : PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP nsDNSRecord::GetNextAddr(PRUint16 port, PRNetAddr *addr) { // not a programming error to poke the DNS record when it has no more --- old-mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp 2008-01-09 09:25:07.000000000 -0800 @@ -73,6 +73,7 @@ #include "nsIVariant.h" #include "nsChannelProperties.h" #include "nsIOService.h" +#include "nsIDNSService.h" // True if the local cache should be bypassed when processing a request. #define BYPASS_LOCAL_CACHE(loadFlags) \ @@ -1025,7 +1026,8 @@ if (NS_FAILED(rv)) return rv; - return pps->AsyncResolve(mURI, 0, this, getter_AddRefs(mProxyRequest)); + return pps->AsyncResolve(mURI, nsIDNSService::RESOLVE_EXTENDED_ERRS, + this, getter_AddRefs(mProxyRequest)); } PRBool --- old-mozilla/docshell/base/nsWebShell.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/docshell/base/nsWebShell.cpp 2008-01-09 09:25:07.000000000 -0800 @@ -837,6 +837,8 @@ // Errors to be shown only on top-level frames if ((aStatus == NS_ERROR_UNKNOWN_HOST || + aStatus == NS_ERROR_DNSSEC_VALIDATION_ERROR || + aStatus == NS_ERROR_DNSSEC_DNE_ERROR || aStatus == NS_ERROR_CONNECTION_REFUSED || aStatus == NS_ERROR_UNKNOWN_PROXY_HOST || aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) && --- old-mozilla/netwerk/base/src/nsPACMan.cpp.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/netwerk/base/src/nsPACMan.cpp 2008-01-09 09:25:07.000000000 -0800 @@ -124,7 +124,8 @@ if (NS_FAILED(rv)) return rv; - rv = dns->AsyncResolve(host, 0, this, eventQ, getter_AddRefs(mDNSRequest)); + rv = dns->AsyncResolve(host, nsIDNSService::RESOLVE_EXTENDED_ERRS, this, + eventQ, getter_AddRefs(mDNSRequest)); if (NS_FAILED(rv)) NS_WARNING("DNS AsyncResolve failed"); --- old-mozilla/docshell/resources/content/netError.xhtml.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/docshell/resources/content/netError.xhtml 2008-01-09 09:25:07.000000000 -0800 @@ -150,6 +150,8 @@ <div id="errorContainer"> <div id="errorTitlesContainer"> <h1 id="et_generic">&generic.title;</h1> + <h1 id="et_dnsDNSSECValidationError">&dnsDNSSECValidationError.title;</h1> + <h1 id="et_dnsDNSSECDNEError">&dnsDNSSECDNEError.title;</h1> <h1 id="et_dnsNotFound">&dnsNotFound.title;</h1> <h1 id="et_fileNotFound">&fileNotFound.title;</h1> <h1 id="et_malformedURI">&malformedURI.title;</h1> @@ -168,6 +170,8 @@ <div id="errorDescriptionsContainer"> <div id="ed_generic">&generic.longDesc;</div> <div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div> + <div id="ed_dnsDNSSECValidationError">&dnsDNSSECValidationError.longDesc;</div> + <div id="ed_dnsDNSSECDNEError">&dnsDNSSECDNEError.longDesc;</div> <div id="ed_fileNotFound">&fileNotFound.longDesc;</div> <div id="ed_malformedURI">&malformedURI.longDesc;</div> <div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div> --- old-mozilla/dom/locales/en-US/chrome/appstrings.properties.orig 2008-05-08 14:04:48.000000000 -0700 +++ mozilla/dom/locales/en-US/chrome/appstrings.properties 2008-01-09 09:25:07.000000000 -0800 @@ -37,6 +37,8 @@ malformedURI=The URL is not valid and cannot be loaded. fileNotFound=The file %S cannot be found. Please check the location and try again. dnsNotFound=%S could not be found. Please check the name and try again. +dnsDNSSECValidationError=%S failed its DNSSEC security check validation. Please contact a security or system administrator for help. +dnsDNSSECDNEError=%S does not exist within the DNS. Please check the name and try again. protocolNotFound=%S is not a registered protocol. connectionFailure=The connection was refused when attempting to contact %S. netInterrupt=The connection to %S has terminated unexpectedly. Some data may have been transferred. --- old-mozilla/nsprpub/pr/src/misc/prerr.c.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/nsprpub/pr/src/misc/prerr.c 2008-01-09 09:25:07.000000000 -0800 @@ -117,11 +117,13 @@ {"PR_CONNECT_ABORTED_ERROR", "Connection aborted"}, {"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"}, {"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"}, + {"PR_DNSSEC_VALIDATION_ERROR", "The DNS record failed DNSSEC validation"}, + {"PR_DNSSEC_DNE_ERROR", "The DNS record does not exist"}, {"PR_MAX_ERROR", "Placeholder for the end of the list"}, {0, 0} }; -static const struct PRErrorTable et = { text, "prerr", -6000L, 76 }; +static const struct PRErrorTable et = { text, "prerr", -6000L, 78 }; void nspr_InitializePRErrorTable(void) { PR_ErrorInstallTable(&et); --- old-mozilla/nsprpub/pr/include/prerr.h.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/nsprpub/pr/include/prerr.h 2008-01-09 09:25:07.000000000 -0800 @@ -269,8 +269,14 @@ /* The library is not loaded */ #define PR_LIBRARY_NOT_LOADED_ERROR (-5926L) +/* The DNS record failed DNSSEC validation */ +#define PR_DNSSEC_VALIDATION_ERROR (-5925L) + +/* The DNS record failed DNSSEC validation */ +#define PR_DNSSEC_DNE_ERROR (-5924L) + /* Placeholder for the end of the list */ -#define PR_MAX_ERROR (-5925L) +#define PR_MAX_ERROR (-5923L) extern void nspr_InitializePRErrorTable(void); #define ERROR_TABLE_BASE_nspr (-6000L) --- old-mozilla/nsprpub/pr/src/misc/prerr.et.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/nsprpub/pr/src/misc/prerr.et 2008-01-09 09:25:07.000000000 -0800 @@ -133,6 +133,8 @@ ec PR_CONNECT_ABORTED_ERROR, "Connection aborted" ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable" ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded" +ec PR_DNSSEC_VALIDATION_ERROR, "The DNS record failed DNSSEC validation" +ec PR_DNSSEC_DNE_ERROR, "The DNS record does not exist" ec PR_MAX_ERROR, "Placeholder for the end of the list" --- old-mozilla/nsprpub/pr/src/misc/prerr.properties.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/nsprpub/pr/src/misc/prerr.properties 2008-01-09 09:25:07.000000000 -0800 @@ -113,4 +113,6 @@ PR_CONNECT_ABORTED_ERROR=Connection aborted PR_HOST_UNREACHABLE_ERROR=Host is unreachable PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded +PR_DNSSEC_VALIDATION_ERROR=The DNS record failed DNSSEC validation +PR_DNSSEC_DNE_ERROR=The DNS record does not exist PR_MAX_ERROR=Placeholder for the end of the list --- old-mozilla/docshell/base/nsDocShell.cpp.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/docshell/base/nsDocShell.cpp 2008-01-09 09:25:07.000000000 -0800 @@ -949,12 +949,6 @@ } } } - // Now make sure our editor, if any, is torn down before we go - // any farther. - if (mEditorData) { - mEditorData->TearDownEditor(); - } - return NS_OK; } @@ -3035,6 +3029,24 @@ formatStrCount = 1; error.AssignLiteral("dnsNotFound"); } + else if (NS_ERROR_DNSSEC_VALIDATION_ERROR == aError) { + NS_ENSURE_ARG_POINTER(aURI); + // Get the host + nsCAutoString host; + aURI->GetHost(host); + CopyUTF8toUTF16(host, formatStrs[0]); + formatStrCount = 1; + error.Assign(NS_LITERAL_STRING("dnsDNSSECValidationError")); + } + else if (NS_ERROR_DNSSEC_DNE_ERROR == aError) { + NS_ENSURE_ARG_POINTER(aURI); + // Get the host + nsCAutoString host; + aURI->GetHost(host); + CopyUTF8toUTF16(host, formatStrs[0]); + formatStrCount = 1; + error.Assign(NS_LITERAL_STRING("dnsDNSSECDNEError")); + } else if(NS_ERROR_CONNECTION_REFUSED == aError) { NS_ENSURE_ARG_POINTER(aURI); // Build up the host:port string. @@ -5667,33 +5679,9 @@ // Now we simulate appending child docshells for subframes. for (i = 0; i < childShells.Count(); ++i) { nsIDocShellTreeItem *childItem = childShells.ObjectAt(i); - nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); - - // Make sure to not clobber the state of the child. Since AddChild - // always clobbers it, save it off first. - PRBool allowPlugins; - childShell->GetAllowPlugins(&allowPlugins); - - PRBool allowJavascript; - childShell->GetAllowJavascript(&allowJavascript); - - PRBool allowRedirects; - childShell->GetAllowMetaRedirects(&allowRedirects); - - PRBool allowSubframes; - childShell->GetAllowSubframes(&allowSubframes); - - PRBool allowImages; - childShell->GetAllowImages(&allowImages); - AddChild(childItem); - childShell->SetAllowPlugins(allowPlugins); - childShell->SetAllowJavascript(allowJavascript); - childShell->SetAllowMetaRedirects(allowRedirects); - childShell->SetAllowSubframes(allowSubframes); - childShell->SetAllowImages(allowImages); - + nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem); rv = childShell->BeginRestore(nsnull, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); } @@ -6841,33 +6829,6 @@ // If we have a saved content viewer in history, restore and show it now. if (aSHEntry && (mLoadType & LOAD_CMD_HISTORY)) { - // It's possible that the previous viewer of mContentViewer is the - // viewer that will end up in aSHEntry when it gets closed. If that's - // the case, we need to go ahead and force it into its shentry so we - // can restore it. - if (mContentViewer) { - nsCOMPtr<nsIContentViewer> prevViewer; - mContentViewer->GetPreviousViewer(getter_AddRefs(prevViewer)); - if (prevViewer) { -#ifdef DEBUG - nsCOMPtr<nsIContentViewer> prevPrevViewer; - prevViewer->GetPreviousViewer(getter_AddRefs(prevPrevViewer)); - NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here"); -#endif - nsCOMPtr<nsISHEntry> viewerEntry; - nsCOMPtr<nsIContentViewer_MOZILLA_1_8_BRANCH2> - prevViewerBranch(do_QueryInterface(prevViewer)); - if (prevViewerBranch) { - prevViewerBranch-> - GetHistoryEntry(getter_AddRefs(viewerEntry)); - } - if (viewerEntry == aSHEntry) { - // Make sure this viewer ends up in the right place - mContentViewer->SetPreviousViewer(nsnull); - prevViewer->Destroy(); - } - } - } nsCOMPtr<nsISHEntry> oldEntry = mOSHE; PRBool restoring; rv = RestorePresentation(aSHEntry, &restoring); --- old-mozilla/netwerk/base/public/nsNetError.h.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/netwerk/base/public/nsNetError.h 2008-01-09 09:25:07.000000000 -0800 @@ -259,6 +259,12 @@ #define NS_ERROR_UNKNOWN_HOST \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 30) +#define NS_ERROR_DNSSEC_VALIDATION_ERROR \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 31) + +#define NS_ERROR_DNSSEC_DNE_ERROR \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 32) + /** * The lookup of a proxy hostname failed. * --- old-mozilla/dom/locales/en-US/chrome/netError.dtd.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/dom/locales/en-US/chrome/netError.dtd 2008-01-09 09:25:07.000000000 -0800 @@ -12,6 +12,12 @@ <!ENTITY dnsNotFound.title "Address Not Found"> <!ENTITY dnsNotFound.longDesc "<p>The browser could not find the host server for the provided address.</p><ul><li>Did you make a mistake when typing the domain? (e.g. <q><strong>ww</strong>.mozilla.org</q> instead of <q><strong>www</strong>.mozilla.org</q>)</li><li>Are you certain this domain address exists? Its registration may have expired.</li><li>Are you unable to browse other sites? Check your network connection and DNS server settings.</li><li>Is your computer or network protected by a firewall or proxy? Incorrect settings can interfere with Web browsing.</li></ul>"> +<!ENTITY dnsDNSSECValidationError.title "DNSSEC Validation Error"> +<!ENTITY dnsDNSSECValidationError.longDesc "The address (URL) failed its DNSSEC security check validation. Please contact a system administrator for help."> + +<!ENTITY dnsDNSSECDNEError.title "Server Does Not Exist"> +<!ENTITY dnsDNSSECDNEError.longDesc "<p>The browser verified that there is no server for the provided address.</p><ul><li>Did you make a mistake when typing the domain? (e.g. <q><strong>ww</strong>.mozilla.org</q> instead of <q><strong>www</strong>.mozilla.org</q>)</li><li>This domain address does not exist. Are you sure it is supposed to? Maybe it used to but it no longer does?</li></ul>"> + <!ENTITY fileNotFound.title "File Not Found"> <!ENTITY fileNotFound.longDesc "<ul><li>Could the item have been renamed, removed, or relocated?</li><li>Is there a spelling, capitalization, or other typographical error in the address?</li><li>Do you have sufficient access permissions to the requested item?</li></ul>"> --- old-mozilla/config/autoconf.mk.in.orig 2008-05-08 14:04:49.000000000 -0700 +++ mozilla/config/autoconf.mk.in 2008-05-08 14:08:19.000000000 -0700 @@ -253,7 +253,7 @@ OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) @COMPILE_CXXFLAGS@ OS_INCLUDES = $(NSPR_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(ZLIB_CFLAGS) -OS_LIBS = @LIBS@ +OS_LIBS = @VAL_LIBS@ @LIBS@ ACDEFINES = @MOZ_DEFINES@ MOZ_OPTIMIZE = @MOZ_OPTIMIZE@ @@ -485,6 +485,9 @@ MOZ_ENABLE_XINERAMA = @MOZ_ENABLE_XINERAMA@ MOZ_XINERAMA_LIBS = @MOZ_XINERAMA_LIBS@ +VALIDAT_LIBS = @VALIDAT_LIBS@ +SYSTEM_VALIDAT = @SYSTEM_VALIDAT@ + MOZ_XIE_LIBS = @MOZ_XIE_LIBS@ XT_LIBS = @XT_LIBS@ --- old-mozilla/nsprpub/pr/src/misc/prnetdb.c.orig 2008-05-08 14:30:53.000000000 -0700 +++ mozilla/nsprpub/pr/src/misc/prnetdb.c 2008-05-08 14:30:53.000000000 -0700 @@ -39,6 +39,10 @@ #include <string.h> +#ifdef MOZ_DNSSEC +#include <validator/validator.h> +#endif + /* * On Unix, the error code for gethostbyname() and gethostbyaddr() * is returned in the global variable h_errno, instead of the usual @@ -66,8 +70,8 @@ * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return * a struct hostent* pointer. For example, Solaris and IRIX. */ -#if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \ - || defined(_PR_HAVE_THREADSAFE_GETHOST) +#if (defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \ + || defined(_PR_HAVE_THREADSAFE_GETHOST)) #define _PR_NO_DNS_LOCK #endif @@ -634,6 +638,218 @@ } #endif /* !defined(_PR_HAVE_GETPROTO_R) */ +#define DNSSEC_FAILURE 0 +#define DNSSEC_SUCCESS 1 +/* START DNSSEC INTERNAL */ +#define DODNSSECDEBUG +#ifdef DODNSSECDEBUG +#define DNSSECDEBUG(x) fprintf x; +#define DNSSECFUNBEGIN() \ + { \ + fprintf(stderr, "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"); \ + fprintf(stderr, "BEGIN %s:%d: \n ", __FUNCTION__, __LINE__); \ + } +#define DNSSECFUNDEBUG(x) { DNSSECFUNBEGIN(); DNSSECDEBUG(x); } +#define DNSSECFUNEXIT() { \ + fprintf(stderr, "EXIT %s:%d: \n", __FUNCTION__, __LINE__); \ + fprintf(stderr, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); \ + } +#define DNSSECFUNRETURN(retval) \ + { \ + DNSSECDEBUG((stderr, " returning: %x", (unsigned int) retval)); \ + if ((int) retval == DNSSEC_SUCCESS) { \ + DNSSECDEBUG((stderr, " (success)")); \ + } else if ((int) retval == DNSSEC_SUCCESS || (int) retval == -1) { \ + DNSSECDEBUG((stderr, " (FAIL)")); \ + } \ + DNSSECDEBUG((stderr, "\n")); \ + DNSSECFUNEXIT(); \ + return retval; \ + } +#else +#define DNSSECDEBUG(x) +#define DNSSECFUNDEBUG(x) +#define DNSSECFUNEXIT() +#define DNSSECFUNRETURN(retval) return retval; +#endif +/* END DNSSEC INTERNAL */ + + +/* 0 = enforce system policy, 1 = ignore, 2 = always secure */ +int global_policy = 0; +#define DNSSEC_POLICY_ENFORCE_SYS_POLICY 0 +#define DNSSEC_POLICY_IGNORE 1 +#define DNSSEC_POLICY_ALWAYS_SECURE 2 +void +PR_set_dnssec_validate_policy(int policy) +{ + DNSSECFUNDEBUG((stderr, "DNSSEC Setting policy: %d\n", policy)); + global_policy = policy; +} + + +#ifdef MOZ_DNSSEC +/* XXX: include drop or configurize */ +#include <stdio.h> +#include <netdb.h> + +/* prototypes */ +int dnssec_check_policy(int dnssec_status, int policytype); +/** + * dnssec_validate(HOSTNAME) + * + * attempts to validate HOSTNAME using dnssec. It will return one of: + * + * If global_policy = DNSSEC_POLICY_IGNORE + * - DNSSEC_SUCCESS: + * + * If global_policy = DNSSEC_POLICY_ENFORCE_SYS_POLICY + * - DNSSEC_SUCCESS if verified + * - DNSSEC_FAILURE if not + * + * If global_policy = DNSSEC_POLICY_ENFORCE_SYS_POLICY + * - DNSSEC_SUCCESS if verified + * - DNSSEC_FAILURE if not + */ +/* XXX: pass in address type? */ +int dnssec_validate (const char *domain_name) { + int dnssec_status; + struct hostent hentry, *hentryp; + char buf[1024]; + size_t buflen = sizeof(buf); + int h_errno; + val_status_t val_status; + + DNSSECFUNDEBUG((stderr, "DNSSECvalidating: %s\n", domain_name)); + + /* don't even bother validating when the policy doesn't call for it */ + if (global_policy == DNSSEC_POLICY_IGNORE) { + DNSSECDEBUG((stderr, " OK: policy is always allow\n")); + DNSSECFUNRETURN(DNSSEC_SUCCESS); + } + + /* explicitly catch localhost */ + if (strcmp(domain_name, "localhost") == 0) { + DNSSECDEBUG((stderr, " OK: 'localhost' is always allowed\n")); + DNSSECFUNRETURN(DNSSEC_SUCCESS); + } + + /* attempt a lookup */ + dnssec_status = val_gethostbyname_r(NULL, domain_name, &hentry, + buf, buflen,&hentryp, &h_errno, + &val_status); + + /* check the results, or assume indeterminate if we don't know why + the above failed */ + DNSSECDEBUG((stderr, " val_gethostbyname returned %d,val_st=%d,errno=%d,ptr=%x\n", dnssec_status, val_status, h_errno, (unsigned int) hentryp)); + if (!hentryp && val_status == VAL_DONT_KNOW) // Should never happen? + val_status = VAL_BOGUS; + + DNSSECDEBUG((stderr, " val_gethostbyname's dnssec status was %d\n", dnssec_status)); + + if (dnssec_check_policy(val_status, global_policy) == DNSSEC_SUCCESS) + DNSSECFUNRETURN(DNSSEC_SUCCESS); + + DNSSECFUNRETURN(DNSSEC_FAILURE); +} + +int +dnssec_check_policy(int val_status, int policytype) +{ + DNSSECFUNDEBUG((stderr, "input: policy=%d, status=%d = %s\n", policytype, val_status, p_val_error(val_status))); + + /* + * POLICY: if val_status == VAL_AC_UNSET then return SUCCESS (unknown host) + * (this is already an error) + */ + if (val_status == VAL_AC_UNSET) + DNSSECFUNRETURN(DNSSEC_SUCCESS); + + /* + * POLICY: ignore errors + */ + if (policytype == DNSSEC_POLICY_IGNORE) + DNSSECFUNRETURN(DNSSEC_SUCCESS); + + /* + * POLICY: require only when possible + * -- IE, trust the policy specified in dnssec-tools's dnsval.conf + */ + if (policytype == DNSSEC_POLICY_ENFORCE_SYS_POLICY) { + if (val_istrusted(val_status)) + DNSSECFUNRETURN(DNSSEC_SUCCESS); + DNSSECFUNRETURN(DNSSEC_FAILURE); + } + + /* + * POLICY: always secure. + * -- IE, require all lookups to return only secure results + */ + + if (val_isvalidated(val_status)) + DNSSECFUNRETURN(DNSSEC_SUCCESS); + DNSSECFUNRETURN(DNSSEC_FAILURE); +} + +struct hostent * +dnssec_gethostbyname(const char *name, + struct hostent *ret, char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + val_status_t val_status; + int ret_stat; + + DNSSECFUNDEBUG((stderr, "input: name=%s\n", name)); + ret_stat = val_gethostbyname_r(NULL, name, ret, buf, buflen, result, h_errnop, + &val_status); + if (!ret_stat) { + DNSSECDEBUG((stderr, " ERROR: ret_stat=%d returned\n", ret_stat)); + DNSSECFUNRETURN(NULL); + } + + if (dnssec_check_policy(val_status, global_policy) == DNSSEC_SUCCESS) { + DNSSECDEBUG((stderr, " policy = success\n")); + DNSSECFUNRETURN(ret); + } + /* XXX: if ret exists (but policy says no), free it? */ + DNSSECDEBUG((stderr, " failed to lookup host\n")); + DNSSECFUNRETURN(NULL); +} + +struct hostent * +dnssec_gethostbyname2(const char *name, int af, + struct hostent *ret, char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + val_status_t val_status; + int ret_stat; + + DNSSECFUNDEBUG((stderr, "input: name=%s\n", name)); + ret_stat = val_gethostbyname2_r(NULL, name, af, + ret, buf, buflen, result, h_errnop, + &val_status); + if (!ret_stat) { + DNSSECDEBUG((stderr, " ERROR: ret_stat=%d returned\n", ret_stat)); + DNSSECFUNRETURN(NULL); + } + + if (dnssec_check_policy(val_status, global_policy) == DNSSEC_SUCCESS) { + DNSSECDEBUG((stderr, " policy = success\n")); + DNSSECFUNRETURN(ret); + } + /* XXX: if ret exists (but policy says no), free it? */ + DNSSECDEBUG((stderr, " failed to lookup host\n")); + DNSSECFUNRETURN(NULL); +} + +#else /* !MOZ_DNSSEC */ + +int dnssec_validate (const char *domain_name) { + return DNSSEC_SUCCESS; +} + +#endif /* !MOZ_DNSSEC */ + /* * ################################################################# * NOTE: tmphe, tmpbuf, bufsize, h, and h_err are local variables @@ -669,7 +885,47 @@ #endif /* definition of GETHOSTBYXXX */ -PR_IMPLEMENT(PRStatus) PR_GetHostByName( +/* override functions if MOZ_DNSSEC is enabled */ +#ifdef MOZ_DNSSEC + +/* We do this in a special section to allow the GETHOSTBYADDR to be + pulled above as normal. Unfortunately, even though the DNSSEC APIs + are thread safe, if GETHOSTBYADDR is not then we'll still perform + safe locking because this code doesn't differentiate between calls + at all. +*/ +#undef GETHOSTBYNAME +#undef GETHOSTBYNAME2 + +#define GETHOSTBYNAME(name) \ + (dnssec_gethostbyname(name, &tmphe, tmpbuf, bufsize, &h, &h_err), h) +#define GETHOSTBYNAME2(name, af) \ + (dnssec_gethostbyname2(name, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h) + +#endif /* MOZ_DNSSEC */ + +/* note: not DNSSEC specific, but only currently needed for DNSSEC */ +/* converts a return value from one which may include other (newer) + DNS error codes like those provided by DNSSEC validation to + something which older code can still understand */ +static void simplify_return_value(void) +{ + PRErrorCode errcode = PR_GetError(); + switch(errcode) { + /* Pass the original codes */ + case PR_DNSSEC_VALIDATION_ERROR: + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, 0); + break; + case PR_DNSSEC_DNE_ERROR: + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, 0); + break; + default: + /* everything else can pass on as before */ + break; + } +} + +PR_IMPLEMENT(PRStatus) PR_GetHostByNameExtended( const char *name, char *buf, PRIntn bufsize, PRHostEnt *hp) { struct hostent *h; @@ -682,6 +938,7 @@ #endif if (!_pr_initialized) _PR_ImplicitInitialization(); + DNSSECFUNDEBUG((stderr, "input=%s\n", name)); #if defined(_PR_HAVE_GETHOST_R) tmpbuf = localbuf; @@ -691,7 +948,7 @@ if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - return rv; + DNSSECFUNRETURN(rv); } } #endif @@ -703,13 +960,17 @@ #else h = GETHOSTBYNAME(name); #endif - - if (NULL == h) + + /* XXX */ + DNSSECDEBUG((stderr, "DNSSECgethostbyname results: host=%s h_errno=%d\n", name, h_errno)); + if (NULL == h) { + DNSSECDEBUG((stderr, "********** Status = LOOKUP_ERROR\n")); PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); } else { + DNSSECDEBUG((stderr, "********** Status = SUCCESS\n")); _PRIPAddrConversion conversion = _PRIPAddrNoConversion; rv = CopyHostent(h, &buf, &bufsize, conversion, hp); if (PR_SUCCESS != rv) @@ -720,7 +981,17 @@ if (tmpbuf != localbuf) PR_Free(tmpbuf); #endif - return rv; + DNSSECFUNRETURN(rv); +} + +PR_IMPLEMENT(PRStatus) PR_GetHostByName( + const char *name, char *buf, PRIntn bufsize, PRHostEnt *hp) +{ + PRStatus ret; + DNSSECFUNDEBUG((stderr, "input=%s\n", name)); + ret = PR_GetHostByNameExtended(name, buf, bufsize, hp); + simplify_return_value(); + return ret; } #if !defined(_PR_INET6) && \ @@ -810,7 +1081,7 @@ } #endif -PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( +PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNameExtended( const char *name, PRUint16 af, PRIntn flags, char *buf, PRIntn bufsize, PRHostEnt *hp) { @@ -831,11 +1102,12 @@ PRBool did_af_inet = PR_FALSE; #endif + DNSSECFUNDEBUG((stderr, "input=%s\n", name)); if (!_pr_initialized) _PR_ImplicitInitialization(); if (af != PR_AF_INET && af != PR_AF_INET6) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return PR_FAILURE; + DNSSECFUNRETURN(PR_FAILURE); } #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) @@ -878,11 +1150,13 @@ if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - return rv; + DNSSECFUNRETURN(rv); } } #endif + /* XXX: should be able to map gethostbyname2 -> getaddrinfo with hints */ + /* Do not need to lock the DNS lock if getipnodebyname() is called */ #ifdef _PR_INET6 #ifdef _PR_HAVE_GETHOSTBYNAME2 @@ -940,6 +1214,7 @@ if (NULL == h) { + DNSSECDEBUG((stderr, " lookup failed\n")); #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) @@ -998,7 +1273,18 @@ PR_Free(tmpbuf); #endif - return rv; + DNSSECFUNRETURN(rv); +} + +PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( + const char *name, PRUint16 af, PRIntn flags, + char *buf, PRIntn bufsize, PRHostEnt *hp) +{ + PRStatus ret; + DNSSECFUNDEBUG((stderr, "input=%s\n", name)); + ret = PR_GetIPNodeByName(name, af, flags, buf, bufsize, hp); + simplify_return_value(); + return ret; } PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( @@ -1020,6 +1306,7 @@ int error_num; #endif + DNSSECFUNDEBUG((stderr, "input=%x", (unsigned int) hostaddr)); if (!_pr_initialized) _PR_ImplicitInitialization(); if (hostaddr->raw.family == PR_AF_INET6) @@ -1165,7 +1452,7 @@ PR_Free(tmpbuf); #endif - return rv; + DNSSECFUNRETURN(rv); } /******************************************************************************/ @@ -1777,6 +2064,7 @@ PRStatus status = PR_SUCCESS; PRIntn rv; + DNSSECFUNDEBUG((stderr,"input=%s\n",string)); #if defined(_PR_HAVE_INET_NTOP) rv = inet_pton(AF_INET6, string, &addr->ipv6.ip); if (1 == rv) @@ -1788,23 +2076,26 @@ PR_ASSERT(0 == rv); /* clean up after the failed inet_pton() call */ memset(&addr->ipv6.ip, 0, sizeof(addr->ipv6.ip)); + /* XXX */ + LOCK_DNS(); rv = inet_pton(AF_INET, string, &addr->inet.ip); if (1 == rv) { - addr->raw.family = AF_INET; + addr->raw.family = AF_INET; } else { - PR_ASSERT(0 == rv); - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - status = PR_FAILURE; + PR_ASSERT(0 == rv); + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + status = PR_FAILURE; } + UNLOCK_DNS(); } #else /* _PR_HAVE_INET_NTOP */ rv = StringToV6Addr(string, &addr->ipv6.ip); if (1 == rv) { addr->raw.family = PR_AF_INET6; - return PR_SUCCESS; + DNSSECFUNRETURN(PR_SUCCESS); } PR_ASSERT(0 == rv); /* clean up after the failed StringToV6Addr() call */ @@ -1826,7 +2117,7 @@ } #endif /* _PR_HAVE_INET_NTOP */ - return status; + DNSSECFUNRETURN(status); } PR_IMPLEMENT(PRStatus) PR_NetAddrToString( @@ -1940,17 +2231,26 @@ * provide getaddrinfo in all versions that NSPR cares to support. */ -#if defined(_PR_HAVE_GETADDRINFO) +#ifdef MOZ_DNSSEC +#define GETADDRINFO(a,b,c,d) val_getaddrinfo(NULL, a, b, c, d, &val_status) +#define FREEADDRINFO freeaddrinfo +typedef struct addrinfo PRADDRINFO; +typedef struct addrinfo DNSSECPRADDRINFO; + +#elif defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6) typedef struct addrinfo PRADDRINFO; +typedef struct addrinfo DNSSECPRADDRINFO; + #define GETADDRINFO getaddrinfo #define FREEADDRINFO freeaddrinfo #elif defined(_PR_INET6_PROBE) typedef struct addrinfo PRADDRINFO; +typedef struct addrinfo DNSSECPRADDRINFO; /* getaddrinfo/freeaddrinfo prototypes */ #if defined(WIN32) @@ -2030,9 +2330,6 @@ #endif } -#define GETADDRINFO (*_pr_getaddrinfo) -#define FREEADDRINFO (*_pr_freeaddrinfo) - #endif /* _PR_INET6 */ #endif /* _PR_HAVE_GETADDRINFO */ @@ -2055,45 +2352,58 @@ { PRStatus rv; PRAddrInfoFB *ai; + DNSSECFUNDEBUG((stderr, "input=%s", hostname)); /* fallback on PR_GetHostByName */ ai = PR_NEW(PRAddrInfoFB); if (!ai) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } - rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent); + DNSSECDEBUG((stderr, "DNSSECgethostbyname: %d %s\n", __LINE__, hostname)); + rv = PR_GetHostByNameExtended(hostname, ai->buf, sizeof ai->buf, &ai->hostent); if (rv == PR_FAILURE) { PR_Free(ai); - return NULL; + DNSSECFUNRETURN(NULL); } ai->has_cname = !(flags & PR_AI_NOCANONNAME); - return (PRAddrInfo *) ai; + DNSSECFUNRETURN((PRAddrInfo *) ai); } -PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname, - PRUint16 af, - PRIntn flags) +PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByNameExtended(const char *hostname, + PRUint16 af, + PRIntn flags, + PRUint16 *security_flags) { +#ifdef MOZ_DNSSEC + val_status_t val_status; +#endif + DNSSECFUNDEBUG((stderr, "input=%s\n", hostname)); + + /* wipe the security flags */ + if (security_flags) + *security_flags = PR_DNSSEC_NO_FLAGS; + /* restrict input to supported values */ if ((af != PR_AF_INET && af != PR_AF_UNSPEC) || (flags & ~ PR_AI_NOCANONNAME) != PR_AI_ADDRCONFIG) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return NULL; + DNSSECFUNRETURN(NULL); } if (!_pr_initialized) _PR_ImplicitInitialization(); #if !defined(_PR_HAVE_GETADDRINFO) - return pr_GetAddrInfoByNameFB(hostname, af, flags); + DNSSECFUNRETURN(pr_GetAddrInfoByNameFB(hostname, af, flags)); #else #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present) { - return pr_GetAddrInfoByNameFB(hostname, af, flags); + DNSSECFUNRETURN(pr_GetAddrInfoByNameFB(hostname, af, flags)); } #endif { - PRADDRINFO *res, hints; + PRADDRINFO hints; + DNSSECPRADDRINFO *res; PRStatus rv; /* @@ -2116,18 +2426,73 @@ hints.ai_socktype = SOCK_STREAM; rv = GETADDRINFO(hostname, NULL, &hints, &res); - if (rv == 0) - return (PRAddrInfo *) res; + if (rv == EAI_AGAIN) { + /* temporary failure... odd... try again? */ + PR_Sleep(1000); + DNSSECDEBUG((stderr, "DNSSECgetaddrinfo reted/trying again: %d %d\n", rv, (unsigned int) res)); + rv = GETADDRINFO(hostname, NULL, &hints, &res); + } + DNSSECDEBUG((stderr, "DNSSECgetaddrinfo returned: %d\n", (unsigned int) res)); + +#ifdef MOZ_DNSSEC + if (dnssec_check_policy(val_status, global_policy) != DNSSEC_SUCCESS) { + /* DNSsec validation failed */ + PR_SetErrorText(0, "Host DNSsec validation failed"); + PR_SetError(PR_DNSSEC_VALIDATION_ERROR, 0); + DNSSECDEBUG((stderr, "DNSSECgetaddrinfo: returning failure line:%d %s => val_status:%d\n", __LINE__, hostname, val_status)); + if(res) + FREEADDRINFO(res); + DNSSECFUNRETURN(NULL); + } + + if (!res && val_isvalidated(val_status)) { + /* DNSSEC has proven that the record does not exist; we + return a different error message to show that the lookup + succeeded and there is officially no results */ + PR_SetErrorText(0, "Address does not exist"); + PR_SetError(PR_DNSSEC_DNE_ERROR, 0); + DNSSECDEBUG((stderr, "DNSSECgetaddrinfo: returning DNE failure:%d %s => val_status:%d\n", __LINE__, hostname, val_status)); + DNSSECFUNRETURN(NULL); + } + + /* set the security flags to how the results were achieved */ + if (security_flags) { + if (val_isvalidated(val_status)) + *security_flags |= PR_DNSSEC_IS_VALIDATED; + + if (val_istrusted(val_status)) + *security_flags |= PR_DNSSEC_IS_TRUSTED; + } +#endif + + if (rv == 0) { + DNSSECFUNRETURN((PRAddrInfo *) res); + } + DNSSECDEBUG((stderr, "DNSSECgetaddrinfo failed: %d\n", rv)); PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv); } - return NULL; + DNSSECFUNRETURN(NULL); #endif } +PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname, + PRUint16 af, + PRIntn flags) +{ + struct PRAddrInfo *result; + DNSSECFUNDEBUG((stderr, "input=%s\n", hostname)); + result = PR_GetAddrInfoByNameExtended(hostname, af, flags, NULL); + simplify_return_value(); + DNSSECFUNRETURN(result); +} + + PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai) { -#if defined(_PR_HAVE_GETADDRINFO) +#if defined(MOZ_DNSSEC) + FREEADDRINFO((DNSSECPRADDRINFO *) ai); +#elif defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present) PR_Free((PRAddrInfoFB *) ai); @@ -2144,9 +2509,9 @@ PRUint16 port, PRNetAddr *result) { -#if defined(_PR_HAVE_GETADDRINFO) - PRADDRINFO *ai; -#if defined(_PR_INET6_PROBE) +#if defined(_PR_HAVE_GETADDRINFO) || defined(MOZ_DNSSEC) + DNSSECPRADDRINFO *ai; +#if defined(_PR_INET6_PROBE) && !defined(MOZ_DNSSEC) if (!_pr_ipv6_is_present) { /* using PRAddrInfoFB */ PRIntn iter = (PRIntn)(PRPtrdiff) iterPtr; @@ -2158,9 +2523,9 @@ #endif if (iterPtr) - ai = ((PRADDRINFO *) iterPtr)->ai_next; + ai = ((DNSSECPRADDRINFO *) iterPtr)->ai_next; else - ai = (PRADDRINFO *) base; + ai = (DNSSECPRADDRINFO *) base; if (ai) { /* copy sockaddr to PRNetAddr */